C++ 为什么新的int[n]在int数组[n]无效时有效?
对于以下代码:C++ 为什么新的int[n]在int数组[n]无效时有效?,c++,arrays,C++,Arrays,对于以下代码: foo(int n){ int array[n]; } 我理解这是无效的语法,它是无效的,因为C++标准要求在编译时设置数组大小(虽然有些编译器支持以下语法)。 但是,我也理解以下语法是有效的: bar(int n){ int *array = new int[n]; } 我不明白为什么允许这样做,这与创建一个在运行时确定大小的数组不一样吗?这样做是一种很好的做法,或者如果我需要这样做,我应该使用向量吗?int-array[n]在编译时在调用堆栈上分配一个固定
foo(int n){
int array[n];
}
我理解这是无效的语法,它是无效的,因为C++标准要求在编译时设置数组大小(虽然有些编译器支持以下语法)。 但是,我也理解以下语法是有效的:
bar(int n){
int *array = new int[n];
}
我不明白为什么允许这样做,这与创建一个在运行时确定大小的数组不一样吗?这样做是一种很好的做法,或者如果我需要这样做,我应该使用向量吗?
int-array[n]
在编译时在调用堆栈上分配一个固定长度的数组,因此需要在编译时知道n
(除非使用特定于编译器的扩展来允许在运行时进行分配,但数组仍在堆栈上)
int*array=new int[n]
在运行时在堆上分配动态长度数组,因此编译时不需要知道n
。在第一种情况下,静态分配内存空间来保存整数。这是在编译程序时完成的,因此存储量是不灵活的
在后一种情况下,您动态分配一个内存空间来保存整数。这是在程序运行时完成的,因此所需的存储量是灵活的
第二个调用实际上是一个函数,它与操作系统对话,以便在内存中找到要使用的位置。在第一种情况下不会发生相同的过程。这是因为前者在堆栈上分配,后者在堆上分配 当您在堆栈上分配某些内容时,了解对象的大小对于正确构建它是至关重要的。C99允许在运行时指定大小,这会在构建和拆除上述堆栈时带来一些复杂情况,因为您无法在编译时计算其大小。必须按顺序发出机器代码在程序执行过程中执行所述计算,这可能是这个特性不包含在C++标准中的主要原因。 相反,堆没有固定的结构,顾名思义。任何大小的块都可以不按特定顺序分配,只要它们不重叠,并且您有足够的(虚拟)内存。在这种情况下,在编译时知道大小并不重要 另外,请记住,堆栈的大小是有限的,主要是为了在无限递归消耗所有可用内存之前检测它们。通常,该限制固定在1MB左右,并且很少达到该限制。除非您分配大对象,这些对象应该放在堆中 至于您应该使用什么,可能是一个
std::vector
。但它实际上取决于您正在尝试做什么
还请注意,C++11有一个std::array
类,其大小必须在编译时已知。C++14本应引入std::dynarray
,但它被推迟了,因为在编译时未知大小的堆栈分配方面还有很多工作要做
出于性能原因,通常按顺序分配块,但这不是必需的
²正如所指出的,知道编译时的大小不是一项困难的要求,但它使事情变得更简单。您可以在上静态分配内存,也可以在上动态分配内存 在第一种情况下,您的函数包含一个可能具有可变长度的数组声明,但这是不可能的,因为原始数组在编译时必须具有固定的大小,因为它们是在堆栈上分配的。因此,必须将其大小指定为常量,例如
5
。您可以使用类似的方法:
foo(){
int array[5]; // raw array with fixed size 5
}
使用指针可以为要指向的内存指定可变大小,因为此内存将在堆上动态分配。在第二种情况下,您使用参数n
指定要分配的内存空间
最后,我们可以说指针不是数组:使用指针分配的内存在堆上分配,而为原始数组分配的内存在堆栈上分配
有一些很好的替代原始数组的方法,例如标准容器,它基本上是一个长度大小可变的容器
确保您能理解动态内存分配和静态内存分配之间的差异,堆栈上分配的内存和堆上分配的内存。
< P>这是因为C++语言没有C99中引入的C特性,称为“可变长度数组”(VLA)。 C++在采用这种C特性方面比较落后,因为它的库中的std::vector
类型满足了大多数需求
此外,2011年的标准C倒退,使VLA的一个可选功能
简而言之,VLA允许您使用运行时值来确定在自动存储中分配的本地阵列的大小:
int func(int variable)
{
long array[variable]; // VLA feature
// loop over array
for (size_t i = 0; i < sizeof array / sizeof array[0]; i++) {
// the above sizeof is also a VLA feature: it yields the dynamic
// size of the array, and so is not a compile-time constant,
// unlike other uses of sizeof!
}
}
与VLA不同的是,此对象将一直存在,直到使用
delete[]
显式销毁为止,并且可以从周围的范围返回。您的问题的唯一有效答案是,,因为标准如此规定
<> P>与C99相比,C++从不费心指定可变长度数组(VLAS),所以得到可变大小数组的唯一方法是使用动态分配,使用<代码> MalOC/没有办法从破坏堆栈限制中恢复,错误情况只是没有定义
int *p = new int[variable];
unique_ptr<T[]> array{new T[n]};
int array[n]; //valid iff n is compile-time constant, space known at compile-time
int array[n]; //Cannot have a static array with a runtime value in C++
int * array = new int[n]; //This works because it happens at run-time,
// not at compile-time! Different semantics, similar syntax.
new int[n]
int array[n];
typedef int variable_array[n];