(C++) 当函数完成时,分配在堆栈上的数组发生了什么?

jrb*_*rbn 5 c++ memory-management

我有多年的 Java 开发经验,现在我想切换到 C++,我很难理解内存管理系统。

让我用一个小例子来说明情况:

根据我的理解,您可以在堆栈或堆上分配空间。第一个是通过声明这样的变量来完成的:

 int a[5]
Run Code Online (Sandbox Code Playgroud)

或者

int size = 10;
int a[size]
Run Code Online (Sandbox Code Playgroud)

相反,如果要在堆上分配内存,则可以使用“new”命令来完成。例如像:

int *a = new int[10]; (notice that I haven't tried all the code, so the syntax might be wrong)
Run Code Online (Sandbox Code Playgroud)

两者之间的一个区别是,如果它在函数完成时分配在堆栈上,那么空间会自动释放,而在另一种情况下,我们必须使用 delete() 显式释放它。

现在,假设我有一个这样的类:

class A {
  const int *elements[10];

  public void method(const int** elements) {
    int subarray[10];
    //do something
    elements[0] = subarray;
  }
}
Run Code Online (Sandbox Code Playgroud)

现在,我有几个问题:

  1. 在这种情况下,子数组在堆栈上分配。为什么函数方法执行完后,查看elements[0]还是看到子数组的数据?编译器是否翻译了堆分配中的第一个分配(在这种情况下,这是一个好习惯)?
  2. 如果我将子数组声明为“const”,则编译器不允许我将其分配给元素。为什么不?我认为 const 只涉及无法更改指针,但没有其他问题。
  3. (这可能很愚蠢)假设我想分配的“元素”不是固定的 10 个元素,而是来自构造函数的参数。是否仍然可以在堆栈中分配它,或者构造函数将始终在堆中分配它?

抱歉提出这样的问题(这对于 C 专家程序员来说可能看起来很愚蠢),但是 C++ 的内存管理系统与 Java 非常不同,我想避免泄漏或代码缓慢。提前谢谢了!

Sha*_*our 0

该标准没有讨论堆栈或堆,在这种情况下,您的阵列具有自动存储,在大多数现代系统中,该存储将位于堆栈上。一旦退出作用域然后访问它,保留指向自动对象的指针只是简单的未定义行为。C++ 标准草案3.7.3 第 1 节中说(重点是我的):

显式声明为 register 或未显式声明为 static 或 extern 的块作用域变量具有自动存储期限。这些实体的存储将持续到创建它们的块退出为止。