我正在阅读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.elem为new 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必须具有恒定的大小.