当大小是变量而不是常量时,如何创建数组?

Den*_* S. 1 c c++ constants array-initialization

我有一个接收变量int的方法.该变量构成一个数组大小(请不要给我一个向量).因此,我需要在我的方法中初始化一个const int来初始化一个特定大小的数组.问题:我该怎么做?

void foo(int variable_int){
    int a[variable_int] = {0}; //error
}
Run Code Online (Sandbox Code Playgroud)

zen*_*hoy 6

int *a = new int[variable_int];
Run Code Online (Sandbox Code Playgroud)

完成后,请记得删除[]已分配的空间!

  • 或者更好的是,`std :: vector <int> a(variable_int)`.现在您不需要记住删除它,或调试内存泄漏,否则如果抛出异常将不可避免地出现这些泄漏. (5认同)
  • 对不起,我没有注意到这个奇怪的要求.祝你好好调试内存泄漏. (4认同)
  • @MikeSeymour 同意,但问题要求不使用向量。 (2认同)
  • @MikeSeymour-我和你在一起:使用向量。符合怪异的要求会浪费时间。 (2认同)

pat*_*gan 5

您要求使用非矢量解决方案,但让我们仔细研究一下,因为您可能由于错误的原因而拒绝了它。您不必担心性能,因为在任何称职的编译器手中,它的开销将与任何其他标准一致的解决方案几乎相同。另一方面,我将在下面讨论一些可读性和安全性问题。让我们看看从推荐到最小的方法。

std :: vector

社区最喜欢的容器,这是有充分理由的。它不仅可以声明为运行时大小,而且可以随时更改大小。当尺寸不能预先确定时,例如当重复轮询用户输入时,这便于使用。例子:

// Known size
size_t n;
std::cin >> n;
std::vector<int> vec(n);

// Unknown size
std::vector<int> vec;
int input;
while (std::cin >> input) { // Note: not always the best way to read input
    vec.push_back(in);
}
Run Code Online (Sandbox Code Playgroud)

使用没有太多的缺点std::vector。已知大小的情况恰好需要一种动态分配。在一般情况下,未知大小需要更多,但是无论如何您将无法做得更好。因此,性能或多或少是最佳的。

从语义上讲,对于在整个执行过程中保持恒定的大小可能不是理想的。对于读者来说,可能不明显该容器无意更改。这是不知道的编译器要么所以它可以让你做了错事一样push_back进入vector了一个逻辑常量的大小。

std :: unique_ptr(或std :: shared_ptr)

如果强制使用静态大小,最安全的解决方案对您很重要。

size_t n;
std::cin >> n;
auto arr = std::make_unique<int[]>(n);
Run Code Online (Sandbox Code Playgroud)

arr尽管可以释放当前数组并指向另一个不同大小的数组,但是其大小不能更改。因此,如果在逻辑上您的容器大小是恒定的,则可以更清晰地传达意图。不幸的是,std::vector即使在恒定大小的情况下,它也要弱得多。它不了解大小,因此您必须显式存储大小。出于同样的原因,它不提供迭代器,因此不能在范围内使用。是否要牺牲这些功能来实现静态大小取决于您(和相关项目)。

最初我曾建议过,boost::scoped_array但经过进一步思考,我认为该解决方案没有什么用,所以我会坚持使用标准库。

新[]-删除[]

从技术上讲是一种解决方案,但是除非您被迫使用旧的C ++标准或正在编写内部管理内存的低级库,否则它们绝对比std::unique_ptror std::shared_ptr解决方案差。它们没有提供更多功能,但是安全性明显较低,因为使用完后必须显式释放内存。否则,您将泄漏它,这可能会导致严重的问题。更糟糕的是,delete[]对于执行和异常处理流程复杂的程序,正确使用对于他们来说并非易事。当上述解决方案可供您使用时,请不要使用它!

size_t n;
std::cin >> n;
int* arr = new int[n];
...
// Control flow must reach exactly one corresponding delete[] !!!
delete[] arr;
Run Code Online (Sandbox Code Playgroud)

奖励:编译器扩展

一些编译器可能实际上可以接受以下代码

size_t n;
std::cin >> n;
int arr[n];
Run Code Online (Sandbox Code Playgroud)

依赖于此具有严重的缺点。您的代码无法在所有符合C ++的编译器上进行编译。它甚至可能无法在给定编译器的所有版本上进行编译。另外,我怀疑所生成的可执行文件会n在需要时检查的值并在堆上分配,这意味着您可能会炸毁堆栈。仅当您知道上限n很小且性能对您如此重要以至于您愿意依靠特定于编译器的行为来获得此解决方案时,此解决方案才有意义。这些确实是例外情况。