N = 1,000,000的myArray [N]返回错误,而myArray [1,000,000]不返回错误

时间:2018-11-08 12:36:26

标签: c++ variable-length-array

文件扩展名:.cpp

我有以下代码:

int main() {
    int N; cin >> N;
    int myArray[N];
    return 0;
}

如果我输入N为1,000,000,当我尝试运行该程序时出现错误。但是,当我将myArray[N]设置为myArray[1000000]时,不是这样。为什么会这样?

5 个答案:

答案 0 :(得分:6)

int myArray[N];在C ++中无效。此行为是在C99中引入的,但从未在C ++中引入,可能是因为它使许多丑陋的事情发生在幕后以使其起作用,并且这会使生成的代码效率降低。实际上,此功能在C11中甚至被颠倒了,它的支持仅是可选的,不再是强制性的。请改用std::vector<int>或您选择的任何类似标准容器。

答案 1 :(得分:4)

首先,VLA(可变长度数组)是对C ++的扩展。编译器对此表示支持,因为通常它们还支持标准具备此功能的C。

第二个问题是此数组分配在堆栈上。 堆栈的大小非常有限。因此,当您的N具有很高的价值时,应用程序可能会崩溃,因为堆栈会溢出。

在这种情况下,您应该使用std::vector它将在堆上分配数据。

问题是为什么具有静态数组大小的数组不会崩溃? 可能有几个原因。

  1. 编译器注意到未使用数组,并且根据“好像”规则删除了数组。
  2. 编译器在编译时知道数组的大小,因此知道所需的堆栈大小。此信息可能会传播到链接器,并使用比默认值大的堆栈大小构建应用程序(在一个源代码应用程序的情况下,这是可能的)。免责声明:这是我的猜测,我没有以任何形式(通过测试或编译器文档)对此进行验证,但是我发现了SO answer这证实了我的怀疑。

答案 2 :(得分:2)

之所以会这样,是因为必须在编译时知道静态数组的大小。

强烈建议使用std::vector而不是数组,以提高灵活性和安全性(答案总是总是:如果可能,请使用vector)。您可以使用std::vector::reserve来请求容量至少您想要的长度。使用std::vector::capacity查看当前容量。

#include <iostream>
#include <vector>

int main () {
  std::vector<int> ivec;
  ivec.reserve(100);
  std::cout << ivec.capacity() << std::endl;
  return 0;
}

输出:

100

只有当您有非常好理由而不是向量偏爱数组时,才可以动态分配数组。使用std::shared_ptr使此过程更加安全和方便。这是您想要的方式:

#include <iostream>
#include <memory>

int main () {
  int N;
  std::cin >> N;
  std::shared_ptr<int> arr_ptr (new int[N],  std::default_delete<int[]>());
  for (int i = 0; i != N; ++i) {
    arr_ptr.get()[i] = i * 2;
  }

  for (int i = 0; i != N; ++i) {
    std::cout << arr_ptr.get()[i] << std::endl;
  }
  return 0;
} 

输入:

10

输出:

0
2
4
6
8
10
12
14
16
18

答案 3 :(得分:1)

之所以会这样,是因为在C++中,必须在编译时知道用array[N]声明的静态数组的大小,因此您的错误很可能是编译器告诉您,他必须事先知道大小。如前所述,在需要动态数组时使用std::vector

答案 4 :(得分:1)

必须在编译时知道静态数组array[N]的大小。

对动态数组使用std::vector

// Example program
#include <iostream>
#include <string>
#include <vector>

int main()
{
    int N; std::cin >> N;
    std::cout << N << std::endl;
    std::vector<int> myArray(N);
    std::cout << myArray.size() << std::endl;
    return 0;
}