没有常量表达式的C++数组大小

Geo*_*rge 22 c++ arrays

我正在阅读Stroustrup的 C++之旅.在第9页,他说:

"数组的大小必须是一个常量表达式."

然后,在pg.16,他使用以下代码示例:

void vector vector_init(Vector& v, int s)
{
  v.elem = new double[s]; // Allocate an array of s doubles
  v.sz = s;
}
Run Code Online (Sandbox Code Playgroud)

s不是一个常数表达式,那么如何初始化v.elemnew double[s]合法?

Bar*_*rry 39

分配的数组(即使用new[]表达式创建的数组)之间存在差异new double[s],其生命周期必须由代码(via delete[])和声明的数组管理,其生命周期仅由其范围管理:

int* p = new int[s];  // allocated array, p has type int*
int q[10];            // declared array, q has type int[10]
std::vector<int> u;   // has member allocated array
std::array<int, 5> v; // has member declared array
Run Code Online (Sandbox Code Playgroud)

区别不是基于堆栈/堆.声明的数组可以堆栈分配(例如new array<int,5>)或不堆栈(例如static double x[100];)

使用已分配的数组,大小不必是常量表达式.大小将被简单地编码到分配器以某种方式产生的存储器块中(例如,在实际数据开始之前的四个前导字节),以便相应的delete[]知道要删除多少元素.

随着宣布阵列(或非分配的数组,没有new/ malloc的/ etc.),大小必须编码入式,使析构函数知道该怎么做.唯一允许的标准数组声明是:

T D[constant-expression_opt];
Run Code Online (Sandbox Code Playgroud)

(其中D是可以是名称或其他数组声明的声明符,等等.)声明的数组不限于堆栈.请注意,为了增加混淆,constant-expression是可选的.

数组在C++中提供了许多混淆源.已分配和声明的数组具有不同的大小规则,不同的管理实践,但您可以将a分配给T*它们,并且它们等效地编入索引.分配的数组一个指针(这就是你得到的全部),但是声明的数组会衰减到一个指针(但是一个数组!).


注意,一个可变长度数组(VLA)的概念.例如,gcc支持它们作为扩展,但它们是非标准的C++.它会定期提出,您可以看到这个问题以获取有关它们的更多信息.


Moh*_*ain 11

创建内存由编译器管理的数组时,其大小必须为(编译时)常量.例如:

int a[5];
const int sz = 7;
int b[sz] = {0};
Run Code Online (Sandbox Code Playgroud)

(例如,某些语言:C(C99以后)支持动态数组大小)

如果你想要一个动态大小的数组(你给出的示例片段),你需要自己为它分配内存,你还需要delete在完成后释放它.这种数组的大小也可以是非const的.此外,您需要自己管理内存,分配可能会失败,运算符(例如sizeof)将对指针而不是数组进行操作.

在现代C++(C++ 11及更高版本)中,即使是stl容器也std::array必须具有恒定的大小.