繁体   English   中英

静态与动态阵列C ++

[英]Static vs. Dynamic Array C++

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,我们不得不删除xdelete [] 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;  
}

C ++标准未定义方法A,但在ISO C99中允许使用方法A,GCC在C ++模式下也支持该方法。 https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html

ISO C99允许使用可变长度自动数组,作为扩展,GCC在C90模式和C ++中接受它们。 这些数组的声明与其他任何自动数组一样,但是其长度不是常量表达式。 存储在声明时分配,并在包含声明的块作用域退出时释放。

我刚刚在这里找到了一些相关的讨论: C ++ 14中的可变长度数组?

简单的答案是: 堆栈空间有限。 您可以期望能够在堆上分配1GiB,但是不能期望能够在堆栈上分配相同的数量。

第一个变量int x[size]; 使用堆栈。 因此, 如果size很大 ,您可能会发现程序因段错误而崩溃 只需通过减少CPU的堆栈指针寄存器即可进行分配。 如果减少太多,内核只会将对堆栈内存的下一次访问视为越界访问,并杀死您的进程。 在实际拍摄之前无法检测到这种情况,也无法有秩序地将其恢复。 内核只是在没有警告的情况下向您开枪。

第二个变体int* x = new int[size]; 使用堆。 这样,只要有足够的可用RAM来支持分配,您就可以期望分配成功。 operator new()将以有序的方式显式地向内核请求内存,并且内核将以有序的方式遵从或发信号通知如此多的内存不可用。 如果发生错误, operator new()将继续引发异常,您可以根据自己的喜好捕获并处理该异常。


在旁边:
如果您的内核正在过度使用其内存(就像任何现代Linux一样),则不能保证在发生错误时会获得异常。 operator new()要求内存而不实际提供任何内容时,内核将仅回答“ ok”,并且稍后可能会发现它无法实现其承诺。 发生这种情况时,它将调用OOM杀手(内存不足杀手),该杀手根据某种启发式方法来射击某些进程。 因此,不要期望不会因为过多的内存消耗而被枪杀。

实际上,这是一种能够实际使用所有可用内存的优化方法:一方面,许多程序实际上并未使用它们分配的所有内存(例如分配大缓冲区,而仅使用其中的一部分)。 另一方面,不可能知道哪些COW(写时复制)映射的页面实际上需要复制。 内核不知道将来需要多少内存,只知道当前是否有足够的内存。


TL; DR:
使用int x[size]; 仅当您可以证明size不会超过较小的最大值时。 如果size在10到100的数量级之间(并且类型本身并没有那么大),则选择它。 使用int* x = new[size]; 在所有其他情况下。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM