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

C++ 当大小是变量而不是常量时,如何创建数组?,c++,c,constants,array-initialization,C++,C,Constants,Array Initialization,我有一个接收变量int的方法。该变量构成一个数组大小(请不要提供向量)。因此,我需要在我的方法中初始化一个常量int来初始化一个特定大小的数组。问题:我该怎么做 void foo(int variable_int){ int a[variable_int] = {0}; //error } 完成分配的空间后,请记住删除它 您可以通过编写const int bar=variable\u int-但是这对您没有帮助。在C++中,具有自动存储的数组的大小必须是编译时常数。您无法将变量转换为编

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

void foo(int variable_int){
    int a[variable_int] = {0}; //error
}

完成分配的空间后,请记住删除它

您可以通过编写
const int bar=variable\u int-但是这对您没有帮助。在C++中,具有自动存储的数组的大小必须是编译时常数。您无法将变量转换为编译时常量,因此您想要的是不可能的

根据您的需要,您可以将
a
作为指针,并使用
new
(然后再
delete
it)分配内存,或者,如果编译时总是知道
foo
的参数,您可以将
foo
转换为如下模板函数:

template<int n> void foo() {
    int a[n] = {0};
}
模板void foo(){
int a[n]={0};
}

要想做你想做的事,你需要使用动态分配。在这种情况下,我会认真建议使用向量代替-这是“正确”的事情在C++中。 但如果您仍然不想使用vector[我无法理解您为什么不使用vector],正确的代码是:

 void foo(int variable_int){
    int *a   = new int[variable_int]();   // Parenthesis to initialize to zero.
    ... do stuff with a ... 
    delete [] a;
 }

正如其他人所建议的,您也可以使用calloc,它具有初始化为零的相同效果,但实际上不是“c++”解决方案

C++不支持可变长度数组。相反,您需要动态分配阵列:

std::vector<int> a(variable_int);

更新:这个问题刚刚更新为“C”标记和“C++”。C(自1999年以来)确实支持可变长度数组,因此您的代码在该语言中应该很好。

如果您使用数组,最好封装它们:

template<typename Type>
class 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);
}
arr
的大小不能更改,但可以使其释放当前阵列并指向另一个不同大小的阵列。因此,如果容器的大小在逻辑上是恒定的,这将以更清晰的方式传达意图。不幸的是,即使在大小不变的情况下,它也比std::vector弱得多。它不知道大小,因此必须显式存储大小。出于同样的原因,它不提供迭代器,也不能用于循环的范围。如果您想牺牲这些特性来强制执行静态大小,这取决于您(以及相关项目)

最初我推荐了
boost::scoped_array
,但经过进一步思考,我认为它在这个解决方案中没有太多功能,因此我将坚持使用标准库

新建[]-删除[]

技术上是一种解决方案,但是除非你被迫使用旧的C++标准或者你写的是一个内部管理内存的低级库,否则它们比 STD::UnQuyJPPT或者<代码> STD::SyrdYPPTR < /C>解决方案要严格得多。它们没有提供更多的功能,但安全性要低得多,因为在使用完内存后,必须显式释放内存。否则,您将泄漏它,这可能会导致重大问题。更糟糕的是,对于执行和异常处理流程复杂的程序来说,正确地使用

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
的上限很小,并且性能对您非常重要,以至于您愿意依赖特定于编译器的行为来获得它时,此解决方案才有意义。这些都是非常特殊的情况。

向量有什么问题?如果失败了,我给你一个智能指针。为什么不给你一个向量呢?如果你只想使用C习惯用法,为什么还要使用C++?嗯,把一个向量看作一个数组,你可以用可变大小初始化它。你确定你不是想把你的问题“C”标记出来吗?@邓贾马尼亚克,大多数的目的是,一个C++ <代码>向量<代码>至少和数组一样好!(如果你以前没有使用C++向量:名字很混乱,它们的行为就更像数组而不是数学向量)。如果你想要(如果你不需要/想要边界检查),你甚至可以用<代码> [C]>运算符来处理向量元素。答案是使用向量。C++不支持可变长度数组,如果没有任何RAI,内存管理将导致内存泄漏。或者更好的是,<代码> STD::vector A(变量BIN)< <代码>。现在你不需要记得删除它,或者调试内存泄漏,否则在抛出异常时不可避免地会出现这些泄漏。@MikeSeymour同意,但问题是不使用向量是一个要求。对不起,我没有注意到这个奇怪的要求。祝德布好运
size_t n;
std::cin >> n;
auto arr = std::make_unique<int[]>(n);
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];