为什么这不起作用:`int arr [size]`但是这样做`int * arr = new int [size]`?

时间:2014-10-02 14:04:14

标签: c++ arrays

我正在学习C ++。来自Java,很多东西对我来说都很奇怪。

在某些时候,我尝试创建一个在运行时确定的大小的数组,如下所示:

int size = functionCall(argument);
int array[size];

这已编译并运行,但在程序中稍后给出了非常奇怪的输出。

有人告诉我,我必须这样做:

int size = functionCall(argument);
int* array = new int[size];

因为new允许动态分配东西,即如果我理解根据只在运行时知道的东西正确分配。

两个问题:

1-我对new的理解是否正确?

2-为什么C ++不允许我的代码的第一个版本?

3 个答案:

答案 0 :(得分:8)

  

在某些时候,我尝试创建一个在运行时确定的大小的数组,如下所示:   这编译并运行,但在程序中稍后给出了非常奇怪的输出。

您创建的是一个名为VLA的非标准扩展(A.K.A. Variable-length Array)。它本来应该有效,但是因为我没有假设你出错了。

  

因为new允许动态分配东西,即如果我理解根据只在运行时知道的东西正确分配。

是的,你的直觉是正确的。

  

1-我对新的理解是否正确?

是。您使用new动态分配内存。但这又开启了另一种蠕虫病毒。

  

2-为什么C ++不允许我的代码的第一个版本?

C ++标准不支持VLA。我觉得这个问题的推理超出了问题的范围。

在任何一种情况下,如果你想要一个基于C ++中的运行时变量的动态数组,我们倾向于使用std::vector。您的代码最终将成为这样:

std::size_t size = get_size();
std::vector<int> arr(size);

现在你可以使用std::vector,好像它是一个普通的C数组。使用std::vector而不是raw new的好处是,它可以减轻您使用delete[]的负担,并且在您到达调用{{1}的行之前遇到异常时,它还提供强大的异常安全性}。

答案 1 :(得分:2)

C ++(与现代C不同)不允许使用在运行时计算的值初始化数组。可以做

int x[size];

在C ++中,但size中包含的值必须由编译器知道。因此,以下是合法的

int const size = 10; // Known at compile-time
int x[size];

但以下不是

int size;
cin >> size; // we only know size at run-time
int x[size]; // ERROR!

这样做的原因是限制是技术性的,我不会在这里讨论,因为你对语言很新。只要知道如果你想声明一个数组(不使用关键字new),你需要在编译时知道它的大小。

作为替代方案,您应该检查容器std::vector,它允许您动态安全地分配数组,而不必使用newdelete

std::vector<int> xs(10); // allocate space for ten ints.

好处是,由于vector的析构函数,您不必担心管理它分配的内存,从而导致更安全的代码。

所以,总结一下:

  1. 是的,您对new的理解是正确的。如果您只知道运行时的大小,则需要动态内存。但是,如果可能的话,请避免使用new:首选vector
  2. C ++根本不允许数组在运行时具有已知的大小。在堆栈上创建的所有数组必须在编译时知道它们的大小。这与允许这样的事情的C不同。

答案 2 :(得分:1)

int size = functionCall(argument);
int* x = new int[size];
编译时不知道

size。它只在运行时才知道。因此,您需要为数组使用heap allocation。编译器无法在编译时知道此数组的大小,因此它必须在运行时请求堆内存分配器在知道size是什么时分配足够的空间。 new关键字是对堆内存的请求。

如果你做了

static const int size = <constexpression>
int x[size];

例如,如果constexpression3(size_t可转换文字)或编译时已知的任何内容,那么它将使用stack allocation,因为编译器会在编译时知道数组应该有多大,你可以这样做。

如果要创建一个连续的int数组,其大小只在运行时已知,则应使用std::vector,它提供了一个可以在运行时动态调整大小的数组的安全包装: / p>

std::vector<int> x(size);

如果您在编译时知道大小,您甚至可以考虑使用std::array,因为它具有静态size()方法,不会占用任何额外的存储空间并且意味着您不需要传递大小同样(但是它会导致每个唯一size编译时的实例化成本):

std::array<int, size> x; // where size is known at compile time