我正在阅读 Stroustrup's C++ 之旅。在第 9 页,他说:
"The size of an array must be a constant expression."
稍后,在 pg. 16、他使用如下代码示例:
void vector vector_init(Vector& v, int s)
{
v.elem = new double[s]; // Allocate an array of s doubles
v.sz = s;
}
这里s
不是常量表达式,那么如何将v.elem
初始化为new double[s]
合法?
最佳答案
已分配 数组(即使用 new[]
表达式创建的数组,如 new double[s]
)之间存在区别,其生命周期必须由代码管理(通过 delete[]
)和 < em>声明的数组,其生命周期仅由其作用域管理:
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
区分不是基于堆栈/堆。声明的数组可以在堆上分配(例如 new array<int,5>
)或不在堆栈上(例如 static double x[100];
)
使用 已分配 数组,大小不必是常量表达式。大小将简单地编码到分配器以某种方式产生的内存块中(例如实际数据开始之前的四个前导字节),以便相应的 delete[]
知道要删除多少元素。
对于 已声明 数组(或未分配数组,没有 new
/malloc
/etc.),大小必须†编码为类型,以便析构函数知道该做什么。唯一允许的标准数组声明是:
T D[constant-expression_opt];
(其中D
是一个声明符,可以是一个名称或另一个数组声明等)声明的数组不限于堆栈。请注意,为了增加混淆,常量表达式是可选的。
数组在 C++ 中提供了许多混淆来源。分配和声明的数组有不同的大小规则,不同的管理实践,但你可以分配一个 T*
到任何一个,它们都被等效索引。分配的数组是一个指针(这就是你得到的全部),但声明的数组衰减指向一个指针(但是一个数组!)。
†请注意,有一个可变长度数组 (VLA) 的概念。 gcc ,例如,支持它们作为扩展,但它们是非标准的 C++。但它会定期提出,您可以看到 this question有关它们的更多信息。
关于没有常量表达式的 C++ 数组大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36178544/