如何根据向量的大小声明数组

How can I declare an array from the size of a vector?

本文关键字:声明 数组 何根 向量      更新时间:2023-10-16

我正试图将向量复制到数组中,但我不知道如何根据向量的大小声明数组。

代码:

int main() {
vector<int> ivec = {1, 2, 3, 4, 5};
constexpr size_t size = ivec.size();
int arr[size];
for(size_t i = 0; i < ivec.size(); ++i)
arr[i] = ivec[i];
for(size_t i : arr)
cout << i << endl;
return 0;
}

然而,我认为这不会编译,因为ivec.size()不能是一个常量表达式(尽管我不确定是否是这样)。在这种情况下,我如何在不必手动输入元素数量的情况下做到这一点?

截至目前,std::vectorsize()不是constexpr,因此您无法在constexpr会话中使用它。因此,您可以尝试对动态大小的数组使用new关键字,但这毫无意义,因为您已经在使用向量了。

vector<int> vi = {1, 2, 3, 4, 5};
int* arr = new int[vi.size()];
std::copy(vi.begin(), vi.end(), arr);
for (unsigned int i = 0; i < vi.size(); i++)
std::cout << arr[i] << " ";
delete[] arr;

注意::您可以将std::begin()用于第二个示例,因为arr[]是一个数组,但不能用于第一个示例,原因是arr*是一个指针。但是,std::copy()同时接受这两种情况,所以应该没问题。

initializer_lists可用于constexpr会话:

constexpr initializer_list<int> il = {1, 2, 3, 4, 5};
int arr[il.size()];
std::copy(il.begin(), il.end(), std::begin(arr));
for (unsigned int i = 0; i < il.size(); i++)
std::cout << arr[i] << " ";

通常,不可能将向量复制到数组中,因为通常的数组是constexpr,而向量大小不是,它是动态大小。也有一些编译器支持的动态数组,但话说回来,它们的大小从来都不是constexpr。我想,你们只需要使用向量。

我不知道你的动机,但。。。

int main() {
vector<int> ivec = {1, 2, 3, 4, 5};
constexpr size_t size = ivec.size();
int* arr = (int*)malloc( sizeof( int * size ) );
for(size_t i = 0; i < ivec.size(); ++i)
arr[i] = ivec[i];
for(size_t i : arr)
cout << i << endl;
free( arr );
return 0;
}

您需要分配内存,因为正如您所说,向量大小不是常数:

int main() {
vector<int> ivec = { 1, 2, 3, 4, 5 };
size_t size = ivec.size();
int *arr = new int[size]; // allocate memory
for (size_t i = 0; i < ivec.size(); ++i)
arr[i] = ivec[i];
for (size_t i = 0; i < size; ++i)
cout << i << endl;
delete [] arr;  // release memory
return 0;
}

您似乎想要获取初始值设定项列表中产生constexpr的元素数量。我知道的唯一方法是使用

#include <cstddef>
template <typename T, std::size_t N>
constexpr std::size_t size(T(&)[N]) {
return N;
}
int main() {
int vec[] = { 1, 2, 3, 4, 5 };
constexpr std::size_t s = size(vec);
int array[s];
std::copy(std::begin(vec), std::end(vec), array);
}

如果您真的需要使用std::vector<T>作为源,那么您将需要分配内存,可能首先使用std::vector<T>!如果你想自己分配内存,你可以这样使用:

std::vector<int> vec = { 1, 2, 3, 4, 5 };
std::unique_ptr<int[]> array(new int[vec.size()]);
std::copy(vec.begin(), vec.end(), array.get());

std::unique_ptr<int[]>的使用确保分配的内存自动释放。

constexpr常量表达式,它是在编译时求值的表达式。它在编译时是已知的,这是constexpr的一个基本特性。

考虑到这一点,您可以看到,在运行时尝试构建一个非动态分配的C样式数组是没有意义的,因为只有在运行时才知道元素的数量。这两个想法是正交的。

从技术角度来看,不能从非常量表达式初始化constexprvector::size()是非constexpr,所以正如你所怀疑的,它不仅不可编译,而且从设计的角度来看,试图从它构建constexpr也是不合乎逻辑的:

constexpr size_t size = ivec.size(); // NO GOOD!

尽管如此,很少需要从vector构建C样式数组。首先使用vector,您已经在做正确的事情。现在不要把它复制到一个糟糕的数组中,把它搞砸了。

vector保证具有连续存储。这意味着在大多数情况下,您可以像使用C样式数组一样使用它。您所需要做的就是将vector中第一个元素的地址(或引用)传递给任何期望C样式数组的对象,它就会正常工作。

void AincentApiFunction (int* array, size_t sizeofArray);
int main()
{
std::vector <int> v;
// ...
AincentApiFunction (&v[0], v.size());
}

我会避免

constexpr size_t size = ivec.size();
int arr[size];

像这个一样

size_t size = ivec.size();
int* arr = new int[size];

然后像处理不断分配的数组一样处理它。阅读有关动态分配阵列的更多信息。别忘了去

delete[] array;

在C++11中,数组可以声明为堆栈上的运行时绑定:(注:这只是根据最新的草案:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf并且可能不是标准的,但是g++与-std=c++11将允许它

注意,is不是constexpression:

8.3.4阵列[dcl.array]

D1〔expressionopt〕属性说明符seqopt

标准示例:

void f(unsigned int n) {
int a[n]; // type of a is “array of runtime bound of int”
}

因此,您只需要删除constexpr:

int main() {
vector<int> ivec = {1, 2, 3, 4, 5};
size_t size = ivec.size();                  // this is fine
int arr[size];
for(size_t i = 0; i < ivec.size(); ++i)
arr[i] = ivec[i];
for(size_t i : arr)
cout << i << endl;
return 0;
}

你的编译器可能允许也可能不允许,所以这取决于你需要成为的严格标准