我尝试使用这个版本:
int n;
cin >> n;
int a[n]; // compiler error
但它不起作用。我做错了什么?
我尝试使用这个版本:
int n;
cin >> n;
int a[n]; // compiler error
但它不起作用。我做错了什么?
有三种标准符合要求的方法可以在编译时声明一个大小未知的数组。按推荐程度从高到低介绍。
社区最喜欢的容器,理由充分。它不仅可以用运行时大小声明,而且大小可以在任何时候更改。当大小无法预先确定时使用这种方法非常方便,例如反复轮询用户输入。示例:
// 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);
}
使用std::vector
没有太多的缺点。在已知大小的情况下,需要一次动态分配。在未知大小的情况下,在一般情况下需要更多动态分配,但无论如何您都无法做得更好。因此性能基本上是最佳的。
从语义上讲,对于整个执行过程中保持不变的大小可能并不理想。读者可能不会意识到该容器不打算更改。编译器也不知道这一点,因此它允许您在逻辑上大小恒定的vector
中执行错误操作,例如push_back
。
std::unique_ptr
(或std::shared_ptr
)如果强制实现静态大小很重要,这是最安全的解决方案。
size_t n;
std::cin >> n;
auto arr = std::make_unique<int[]>(n);
arr
的大小无法改变,但可以释放当前的数组并指向另一个不同大小的数组。因此,如果逻辑上您的容器大小是恒定的,这样传达意图会更清晰。不幸的是,即使在恒定大小的情况下,它也比std::vector
弱得多。它不具有尺寸感知,因此您必须显式存储大小。出于同样的原因,它不提供迭代器,也不能在范围for循环中使用。如果要强制使用静态大小,则由您(和相关项目)决定是否愿意牺牲这些功能。
从技术上讲是一种解决方案,但除非您被迫使用旧的C++标准或者您正在编写一个内部管理内存的低级库,否则它们比std::unique_ptr
或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;
有些编译器可能会允许以下代码。
size_t n;
std::cin >> n;
int arr[n];
依赖此方法有严重的缺点。您的代码无法在所有符合C++标准的编译器上编译。它可能甚至不能在给定编译器的所有版本上编译。此外,我怀疑生成的可执行文件是否检查了n
的值,并在需要时在堆上分配,这意味着您可能会耗尽堆栈。只有当您知道n
的上限很小并且性能对您非常重要以至于您愿意依赖特定于编译器的行为来实现它时,此解决方案才有意义。这些是真正的特殊情况。int n;
cin >> n;
int *a = new int[n];
// use 'a'
delete[] a;
你也可以使用一个 std::vector
:
int n;
cin >> n;
vector<int> a(n);
int n, m;
cin >> n >> m;
int **a = new int*[n];
for(int i = 0; i < n; i++)
a[i] = new int[m];
// use 'a'
for (int i = 0; i < n; i++)
delete[] a[i];
delete[] a;
你还可以拥有一个向量的向量。
n
的vector<int> a[n];
是无法工作的。 - HolyBlackCatnew int[n*m]
并进行索引访问的包装。我再次强调这一点! - Lightness Races in Orbitnew[]
,可以使用make_unique<int[]>(n*m)
或std::vector<int>(n*m)
。索引计算完全相同。 - Ben Voigt谷歌:C++ 动态数组
int n;
cin >> n;
int *a = new int[n];
// use 'a'
delete[] a;
C++没有变长数组。作为替代方案,可以使用动态数组,如@user70960所提到的:
int n(0);
cin >> n;
int *a(new int[n]);
// use 'a'
delete[] a;
你也可以使用向量来执行相同的操作,如下所示:
int n(0);
cin >> n;
vector<int> a(n);
std::vector
代替。 - Algirdas Preidžiusnew
”是以下所有答案中的第一个建议,但应优先选择std::vector
,因为它更安全、更方便。 - HolyBlackCat