如何当大小是一个变量不是一个常量创建一个数组?(How to create an array whe

2019-07-18 13:03发布

我有一个接收变量int的方法。 该变量构成了数组的大小(请不要给我一个向量)。 因此,我需要初始化我的方法内的const int的初始化特定大小的阵列。 问:我该怎么做呢?

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

Answer 1:

int *a = new int[variable_int];

记得删除[]分配的空间,当你用它做!



Answer 2:

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

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

或者,因为你说你不希望使用矢量出于某种原因:

class not_a_vector
{
public:
    explicit not_a_vector(size_t size) : a(new int[size]()) {}
    ~not_a_vector() {delete [] a;}
    int & operator[](size_t i) {return a[i];}
    int   operator[](size_t i) const {return a[i];}

    not_a_vector(not_a_vector const &) = delete;
    void operator=(not_a_vector const &) = delete;

private:
    int * a;
};

not_a_vector a(variable_int);

更新:这个问题刚刚用“C”标记更新以及“C ++”。 C(自1999年),不支持变长数组,所以你的代码应该是在语言精炼。



Answer 3:

你问一个非向量解决方案,但我们去了,因为你可能已经拒绝了错误的原因。 你不应该因为任何有能力的编译器它是将具有几乎相同的开销,就像其他任何标准符合性解决方案的手担心性能。 在另一方面,也有一些可读性和安全问题,我会去到下面。 让我们来看看你能做到这一点从大多数建议最少的方式。

的std ::矢量

社区最喜爱的容器中,并有很好的理由。 它不仅可以与运行时的大小声明,但大小可随时更改。 这有利于使用时大小不能被预先确定,例如,当重复地轮询用户输入。 例子:

// 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 。 已知大小的情况下只需要一个动态分配。 未知大小需要更多的在一般情况下,但你不能做任何更好的反正。 所以性能或多或少优化。

在语义上,它可能不是理想的是在整个执行恒定的大小。 它可能不是显而易见的,这种容器不打算改变读者。 这是不知道的编译器要么所以它可以让你做了错事一样push_back成一个vector逻辑上大小不变的。

的std ::的unique_ptr(或std :: shared_ptr的)

如果执行静态尺寸最安全的办法是对你很重要。

size_t n;
std::cin >> n;
auto arr = std::make_unique<int[]>(n);

arr的大小不能变更,但它可以被制成释放当前阵列和指向不同大小的另一个。 因此,如果你的容器的逻辑大小是固定的,这在传达更清晰的方式意图。 不幸的是,它也比弱得多std::vector ,即使在固定尺寸的情况下。 这不是大小感知,所以你必须明确地存储大小。 出于同样的原因,它不提供迭代器,并且不能在范围内使用for循环。 如果要牺牲这些功能来执行静态大小这是给你(和有问题的项目)。

最初,我曾建议boost::scoped_array但经过进一步思考,我不认为它有很多提供了这种解决方案,所以我会坚持的标准库。

新的[] - 删除[]

技术上的解决方案,但除非你是被迫使用旧的C ++标准,或者你正在编写管理内存的低层次库内部,他们是严格比糟糕std::unique_ptrstd::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小,当性能对您非常重要的,你愿意依赖于特定的编译器行为得到它。 这是一届真正的无与伦比的案件。



Answer 4:

你可以很容易地从一个非const变量一个const变量写const int bar = variable_int; - 但这不会帮助你。 在C ++中具有自动存储阵列的尺寸必须是编译时间常数。 你不能把一个变量插入一个编译时间常数,所以你想要的东西是根本不可能的。

根据您的需求,你可以做a指针,并使用分配内存new (再后来delete它),或者,如果参数foo将始终在编译时是已知的,你可以把foo变成一个像这样的模板函数:

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


Answer 5:

做你想做什么,你将需要使用动态分配。 在这种情况下,我会认真地建议使用矢量来代替 - 这是“正确”的东西在C ++做。

但是,如果你还是不希望使用矢量为什么你就不会超越我],正确的代码是:

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

正如其他人建议,你也可以使用释放calloc,它具有初始化为零的效果相同,但没有真正的“C ++”的解决方案。



Answer 6:

如果您使用数组这是一个好主意,把它们封装:

template<typename Type>
class Vector {
    //...
};

标准库自带的实现: 性病::矢量



文章来源: How to create an array when the size is a variable not a constant?