为什么C++允许未动态分配的可变长度数组?

11

我对C++相对较新,从一开始就被灌输了这样的观念:不能做如下操作:

int x;
cin >> x;
int array[x];

所以您必须使用动态内存。然而,我最近发现上述内容 编译通过(尽管我会收到一个 -pedantic 警告,说它违反了 ISO C++ 标准)。我知道如果不符合标准,这样做显然是一个坏主意,但我之前甚至都不知道这是可能的。

我的问题是,为什么 g++ 允许未经动态分配的可变长度数组,如果这在标准中是不允许的?此外,如果编译器可以做到这一点,为什么它不被包含在标准中呢?


3
关于你最后的问题,为什么C++不支持它们,你可以参考这个问题:https://dev59.com/K3I-5IYBdhLWcg3wYXP8以及被接受的答案中链接的comp.lang.c++线程。 - James McNellis
4个回答

20

C99版本的C语言添加了对可变长度数组(VLAs)的支持。

由于gcc已经支持VLAs以支持C99,因此向g++添加对其的支持可能相对简单。

尽管如此,这是一种特定于实现的语言扩展,如果想要代码具有可移植性,则不建议使用特定于实现的扩展。


1
我不知道它在C标准中。这解释得很好,谢谢! - Maulrus
2
@Maulrus:请记住,这是C标准,与C++标准完全分开。 - Joe D

5
因为它被C99支持。我无法确切地说明为什么它不在C++标准中。但是,它并不像你想象的那样有用,因为如果你不小心,它很容易导致堆栈溢出(因为它通常基于alloca,本身就是非标准的)。另一个错误是返回指向动态数组的指针,这将立即超出范围。

那么在C99中坚持使用动态分配的数组会更好,即使它已经成为标准了? - Maulrus
4
@Maulrus从不使用基于用户输入的变长数组(VLAs)。然而,对于堆分配的数组同样适用。您必须验证用户输入。因此,我认为这里没有特定于VLAs的问题。这是我的粗略指南:如果数据集很小,请使用一个小的静态大小数组和一个int表示使用了多少元素。如果数据集很大,请使用堆。但我并不认为有使用VLAs的情况。 - Johannes Schaub - litb
1
它可能没有出现在1995年的C++标准中,因为那之前还没有变长数组的C99标准化。它可能不会出现在即将发布的标准中,因为vector<>提供了类似的功能。 - David Thornley
@Maulrus: 是的,因为C99没有像C89那样广泛的支持。 - Billy ONeal

3

许多编译器都会支持并扩展标准,这主要有两个原因:

  1. 一些不怀好意的编译器开发者可能认为,增加移开他们的编译器的难度可以延长其使用寿命。
  2. 一些善良的编译器开发者可能认为,在没有成本或成本很低的情况下,给你更多的选项是件好事。

1

所有提到的原因都与它们在C中的存在有关,尽管对于要求存在限制。如果您使用scanf而不是cin实现它,并将其放入.c文件中并使用gcc,则您的示例可能展示了比C所需更灵活的支持。

这几乎只是对alloca(分配自动)的隐式调用,它只是减少堆栈指针(增加堆栈大小)并将新的堆栈指针复制到另一个寄存器中,该寄存器用作分配内存的指针。

区别在于,使用alloca创建的对象不会调用构造函数和析构函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接