多级指针,栈还是堆?
Multilevel pointers, stack or heap?
假设我有这个。
int ***a = new int**;
*a = new int*;
**a = new int;
***a = 18
所以我们有这样的东西。 [*] -> [*] -> [*]->[18]
所有这些指针都在堆栈中吗?它们指向的所有内容都在堆中吗?
第一个指针在堆栈上。其余的在堆上,因为它们是使用 new 分配的。
a
在堆栈上。由 new
创建的其余部分在堆上
假设您的代码内嵌在函数中
int ***a = new int**;
a 在堆栈上。它指向堆上的东西(thing1)
*a = new int*;
a 在堆栈上。它指向 thing1。
thing1 现在指向堆上的其他东西 (thing2)
**a = new int;
a 在堆栈上。它指向 thing1。
堆上的 thing1 指向堆上的 thing2。
thing2 指向堆上的一个 int
***a = 18
a 在堆栈上。它指向 thing1。
堆上的 thing1 指向堆上的 thing2。
thing2 指向堆上的一个 int。
那个 int 现在 = 18.
为了理解代码的作用,堆栈的概念是不必要的。您使用的某些实现可能会将 a
放在堆栈上,但这不会改变代码的含义,并且不需要此细节来理解代码的作用。
如果您不相信我:在 C++ 标准中,堆栈一词仅指 std::stack
和抽象的 堆栈展开 概念。
具体来说,我们必须假设您的代码是如何使用的。让我们假设它在自己的一个块中:
{
int ***a = new int**;
*a = new int*;
**a = new int;
***a = 18;
}
那么我们关心的就是各个存储块的存储时长是多少
a
有自动存储期限。存储一直存在到右大括号。
a
指向动态存储时长int**
类型的存储。存储会一直持续到您明确取消分配它为止 - 在这种情况下,它会比 a
.
长
*a
指向动态存储时长int*
类型的存储。在这里,存储会一直持续到您明确取消分配它为止 - 在这种情况下,它会比 a
.
长
**a
指向动态存储时长int
类型的存储。在这里,存储会一直持续到您明确取消分配它为止 - 在这种情况下,它会比 a
.
长
***a
是存储在**a
指向的一块动态存储中的值int(18)
。
程序的作用及其行为方式与这些存储持续时间有关。它与 a
是否在某个堆栈上无关。如您所知,您已经使用 emscripten 编译了这段代码,并且该值存在于 javascript 变量中。
重要的是 a
的存储持续时间是自动的,在这种情况下它的范围是到块的末尾。您使用 new
分配的所有内容的存储期限是动态的,完全在您的控制之下。
根据显示的代码,没有长期的方法来访问具有动态存储持续时间的三个存储部分:它们将超过 a
的存储持续时间和 一旦块结束就会变成内存泄漏。如果将 a
传递出块,您将能够防止这种情况并保留访问所有三个动态存储持续时间存储片段的方式。
假设我有这个。
int ***a = new int**;
*a = new int*;
**a = new int;
***a = 18
所以我们有这样的东西。 [*] -> [*] -> [*]->[18]
所有这些指针都在堆栈中吗?它们指向的所有内容都在堆中吗?
第一个指针在堆栈上。其余的在堆上,因为它们是使用 new 分配的。
a
在堆栈上。由 new
创建的其余部分在堆上
假设您的代码内嵌在函数中
int ***a = new int**;
a 在堆栈上。它指向堆上的东西(thing1)
*a = new int*;
a 在堆栈上。它指向 thing1。 thing1 现在指向堆上的其他东西 (thing2)
**a = new int;
a 在堆栈上。它指向 thing1。 堆上的 thing1 指向堆上的 thing2。 thing2 指向堆上的一个 int
***a = 18
a 在堆栈上。它指向 thing1。 堆上的 thing1 指向堆上的 thing2。 thing2 指向堆上的一个 int。 那个 int 现在 = 18.
为了理解代码的作用,堆栈的概念是不必要的。您使用的某些实现可能会将 a
放在堆栈上,但这不会改变代码的含义,并且不需要此细节来理解代码的作用。
如果您不相信我:在 C++ 标准中,堆栈一词仅指 std::stack
和抽象的 堆栈展开 概念。
具体来说,我们必须假设您的代码是如何使用的。让我们假设它在自己的一个块中:
{
int ***a = new int**;
*a = new int*;
**a = new int;
***a = 18;
}
那么我们关心的就是各个存储块的存储时长是多少
a
有自动存储期限。存储一直存在到右大括号。a
指向动态存储时长int**
类型的存储。存储会一直持续到您明确取消分配它为止 - 在这种情况下,它会比a
. 长
*a
指向动态存储时长int*
类型的存储。在这里,存储会一直持续到您明确取消分配它为止 - 在这种情况下,它会比a
. 长
**a
指向动态存储时长int
类型的存储。在这里,存储会一直持续到您明确取消分配它为止 - 在这种情况下,它会比a
. 长
***a
是存储在**a
指向的一块动态存储中的值int(18)
。
程序的作用及其行为方式与这些存储持续时间有关。它与 a
是否在某个堆栈上无关。如您所知,您已经使用 emscripten 编译了这段代码,并且该值存在于 javascript 变量中。
重要的是 a
的存储持续时间是自动的,在这种情况下它的范围是到块的末尾。您使用 new
分配的所有内容的存储期限是动态的,完全在您的控制之下。
根据显示的代码,没有长期的方法来访问具有动态存储持续时间的三个存储部分:它们将超过 a
的存储持续时间和 一旦块结束就会变成内存泄漏。如果将 a
传递出块,您将能够防止这种情况并保留访问所有三个动态存储持续时间存储片段的方式。