如何将数组的内容附加到 std::vector?

How to append the content of arrays to a std::vector?

本文关键字:std vector 数组      更新时间:2023-10-16

我有两个数组

float vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f,  0.5f, 0.0f
};  
float normals[] = {
0.0, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f,  0.0f, 1.0f
}; 

我首先想将vertices数组添加到std::vector<float>,然后将normals数组插入向量。

我能想到的是基于sizeof(Array)运行一个循环,并将单个元素推回向量。

这能保证当我重新访问它们时插入的值顺序正确吗?

您可以在向量末尾std::vector::insert元素。

#include <iterator> // std::cbegin, std::cend, std::size
#include <vector>
std::vector<float> vec;
// reserve the memory for unwated reallocations.
vec.reserve(std::size(vertices) + std::size(normals));
vec.insert(vec.end(), std::cbegin(vertices), std::cend(vertices));
vec.insert(vec.end(), std::cbegin(normals), std::cend(normals));

[...]根据sizeof(Array)运行循环并推回 向量的单个元素。这能保证价值观吗 当我重新访问它们时,插入的顺序是否正确?

是的,确实如此。请记住,如果您有权访问 c++17 或更高版本的编译器,则可以使用std::size来查找数组的大小。

您可能希望将这两个数组追加现有std::vector或从中创建一个新数组。在这两种情况下,您很可能都希望一次性保留插入所需的所有内存,以避免额外的不必要的重新分配。

对于前一种情况,您可以使用以下函数模板:

template<size_t... Ns>
void append_to_vector(std::vector<float>& vec, float (&...arrs)[Ns]) {
constexpr auto num_elements_to_append = sizeof...(Ns);
vec.reserve(vec.size() + num_elements_to_append);
(vec.insert(vec.end(), std::cbegin(arrs), std::cend(arrs)),...);
}

verticesnormals追加到现有std::vector<float>将变为:

std::vector<float> vec; // your existing vector
// ...
append_to_vector(vec, vertices, normals);

对于后一种情况 - 即,你想从这两个数组中创建一个新的向量 - 你可以使用以下函数模板,create_vector,它反过来调用append_to_vector

template<size_t... Ns>
std::vector<float> create_vector(float (&...arrs)[Ns]) {
std::vector<float> vec; 
append_to_vector(vec, arrs...);
return vec;
}

从数组创建新向量verticesnormals归结为一行:

auto vec = create_vector(vertices, normals);

您不限于两个数组。由于它们的可变参数性质,您实际上可以为这些函数模板提供任意数量的数组,例如:

auto vec = create_vector(vertices, vertices, normals, vertices, normals); 

上面的行如您所料,即,它创建了一个由verticesvertices(再次(、normalsverticesnormals中的元素串联产生的新向量。

在任何情况下,对于每次调用append_to_vector()最多只会执行一次重新分配,因为对std::vector::reserve()的调用可确保插入新元素所需的内存在插入之前可用。

要将元素插入floats 的std::vector中,可以使用 std::copy:

std::vector<float> my_vector;
my_vector.reserve(std::size(vertices) + std::size(normals)); // optional
std::copy(std::begin(vertices), std::end(vertices), std::back_inserter(my_vector));
std::copy(std::begin(normals), std::end(normals), std::back_inserter(my_vector));

my_vector中元素的顺序将与verticesnormals中的顺序相同。

我们需要在插入数组之前保留内存吗?

从技术上讲,没有。但保留内存可能有助于避免不必要的重新分配。

编辑。

cpp首选项std::vector::reserve注释部分如下:

插入范围时,insert()的范围版本通常更可取,因为它保留了正确的容量增长行为,这与reserve()后跟一系列push_back()不同。

我答案中的食谱有效,但在JeJo的食谱中应该是首选。