为什么堆栈中没有可变大小的数组?

use*_*652 21 c++ arrays dynamic-data

我真的不明白为什么我不能在堆栈上有一个可变大小的数组,所以像

foo(int n) {
   int a[n];
}
Run Code Online (Sandbox Code Playgroud)

据我了解部分数据段的堆栈(-segment),因此它不是"常量".

Alo*_*ave 23

根据C++标准,C++中不允许使用可变长度数组(VLA).
许多编译器(包括gcc)都支持它们作为编译器扩展,但重要的是要注意使用这种扩展的任何代码都是不可移植的.

C++提供了std :: vector,用于实现与VLA类似的功能.


有人提议在C++ 11中引入可变长度数组,但最终被删除了,因为它需要对C++中的类型系统进行大量更改.能够在堆栈上创建小数组而不浪费空间或为未使用的元素调用构造函数的好处被认为对于C++类型系统中的大变化而言不够重要.


Xiy*_*eng 7

请注意,该提案被拒绝,以下内容不再适用.但是,对于未来的C++版本,它可能会复活.

N3639中描述的VLA已经在布里斯托尔会议上被接受,并将成为C++ 14的一部分,以及库对应部分"dynarray".因此,使用C++ 14支持的编译器,我们可以开始编写类似的东西:

void func(int n)
{
    int arr[n];
}
Run Code Online (Sandbox Code Playgroud)

或者使用dynarray:

#include <dynarray>

void func(int n)
{
    std::dynarray<int> arr(n);
}
Run Code Online (Sandbox Code Playgroud)

  • 注意:它后来未被接受,并没有进入C++ 14. (3认同)
  • 请删除此答案,因为它(最终)是错误的。 (2认同)

AlQ*_*fir 5

我将尝试用一个例子来解释这个:

假设你有这个功能:

int myFunc() {
   int n = 16;
   int arr[n];
   int k = 1;
}
Run Code Online (Sandbox Code Playgroud)

程序运行时,它会以这种方式将变量设置到堆栈上:

- n @relative addr 0
- arr[16] @relative addr 4
- k @relative addr 64
TOTAL SIZE: 68 bytes
Run Code Online (Sandbox Code Playgroud)

假设我想将arr调整为4个元素.我打算去做:

delete arr;
arr = new int[4];
Run Code Online (Sandbox Code Playgroud)

现在:如果我以这种方式离开堆栈,堆栈将有未使用空间的漏洞.因此,最聪明的做法是将所有变量从堆栈中的一个位置移动到另一个位置并重新计算它们的位置.但是我们遗漏了一些东西:C++没有动态设置位置,只编译程序时只执行一次.为什么?它很简单:因为没有必要将可变大小的对象放到堆栈上,并且因为在分配/重新分配堆栈空间时使用它们会减慢所有程序的速度.

这不是唯一的问题,还有另一个,甚至更大的问题:当你分配一个数组时,你决定它将占用多少空间,如果你超过可用空间,编译器可以警告你,而不是你让程序分配变量堆栈中的大小数组,您打开安全漏洞,因为您使用这种方法的所有程序都容易受到堆栈溢出的影响.

  • 您要执行“删除 arr;”是什么意思?谁说过那是有效的?`arr` 不是指针。 (2认同)
  • 绝对不。我们正在讨论为什么这些没有作为标准实施。无论如何,问题中甚至没有提到 C99 VLA。 (2认同)