C ++的编译器可能表现不同。由于可以使用以下方法声明C ++中的数组:
方法A:
int size;
cout << "Enter size of array: ";
cin >> size;
int x[size];
for (int i = 0; i < size; i++)
{
//cout << "x[" << i << "] = ";
x[i] = i + 1;
}
方法B
int size;
cout << "Enter size of array: ";
cin >> size;
int *x = new int[size];
for (int i = 0; i < size; i++)
{
//cout << "x[" << i << "] = ";
x[i] = i + 1;
}
通过在运行时中获取用户的输入,两者都正常工作。我知道,使用方法 B ,我们必须删除x
之类的delete [] x
。
int *x = new int[size];
,如果两者的服务相同
目的? new
有什么好处? 以下是我正在测试的代码段:
#include<iostream>
using namespace std;
int main()
{
int size;
cout << "Enter size of array: ";
cin >> size;
//int *x = new int[size];
int x[size];
for (int i = 0; i < size; i++)
{
//cout << "x[" << i << "] = ";
x[i] = i + 1;
}
cout << endl << "Display" << endl;
for (int i = 0; i < size; i++)
{
cout << "x[" << i << "] = " << x[i] << endl;
}
return 0;
}
答案 0 :(得分:3)
C ++标准没有定义方法A,但在ISO C99中允许它,GCC也支持它在C ++模式下。来自https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html:
ISO C99允许使用可变长度自动数组,并且作为 扩展GCC在C90模式和C ++中接受它们。这些数组是 声明像任何其他自动数组,但长度是 不是一个恒定的表达。存储分配在 当块范围包含时,声明和释放 声明退出。
我刚刚在这里找到了一些相关的讨论:Variable Length Arrays in C++14?
答案 1 :(得分:2)
简单的答案是:堆栈空间有限。您可以期望能够在堆上分配1GiB,但您不能指望能够在堆栈上分配相同的数量。 / p>
第一个变体int x[size];
使用堆栈。因此,如果size
很大,您可能会发现程序崩溃并出现段错误。通过简单地减少CPU的堆栈指针寄存器来进行分配。如果你减少太多,内核只会将你对堆栈内存的下一次访问视为越界访问,并终止你的进程。在实际拍摄之前无法检测到这种情况,或者无法以有序的方式从中恢复。内核只是在没有警告的情况下射击你。
第二个变体int* x = new int[size];
使用堆。因此,只要有足够的可用RAM来支持分配,您就可以期望分配成功。 operator new()
将以有序的方式明确地向内核询问内存,并且内核将以有序的方式遵守或发出大量内存的不可用性。如果出现错误,operator new()
将继续抛出异常,您可以随意捕获并处理。
<强>除了强>
如果您的内核过度使用其内存(就像任何现代Linux一样),那么不保证在发生错误时获得异常。当operator new()
在没有实际提供任何内存的情况下询问内存时,内核将只回复“ok”,并且可能稍后发现它无法履行其承诺。当发生这种情况时,它将调用OOM杀手(Out-Of-Memory杀手),它基于一些启发式射击一些进程。因此,永远不要期望不要因为过多的内存消耗而被拍摄。
这实际上是一个能够实际使用所有可用内存的优化:首先,许多程序实际上并没有使用它们分配的所有内存(比如分配一个大缓冲区,但只使用它的一部分)。另一方面,不可能知道哪个COW(写时复制)映射页面实际上需要复制。内核不知道将来需要多少内存,它只知道它当前是否有足够的内存。
<强> TL; DR:强>
仅当您可以证明int x[size];
永远不会超过最小值时才使用size
。如果size
大约是10到100(并且类型本身并不是非常大),那就去吧。在所有其他情况下使用int* x = new[size];
。