47
std::vector<int> a;
std::vector<int> b;
std::vector<int> c;

I would like to concatenate these three vectors by appending b's and c's elements to a. Which is the best way to do this, and why?


1) By using vector::insert:

a.reserve(a.size() + b.size() + c.size());
a.insert(a.end(), b.begin(), b.end());
a.insert(a.end(), c.begin(), c.end());
b.clear();
c.clear();

2) By using std::copy:

a.reserve(a.size() + b.size() + c.size());
std::copy(b.begin(), b.end(), std::inserter(a, a.end()));
std::copy(c.begin(), c.end(), std::inserter(a, a.end()));
b.clear();
c.clear();

3) By using std::move (from C++11):

a.reserve(a.size() + b.size() + c.size());
std::move(b.begin(), b.end(), std::inserter(a, a.end()));
std::move(c.begin(), c.end(), std::inserter(a, a.end()));
b.clear();
c.clear();
4

4 回答 4

25

在我看来,您的第一个解决方案是最好的方法。

vector<>::insert旨在添加元素,因此它是最合适的解决方案。

您可以调用reserve目标向量以保留一些空间,但除非您将大量向量添加在一起,否则它可能不会提供太多好处:vector<>::insert知道将添加多少元素,您将避免只reserve调用一次。

注意:如果它们是vector更复杂的类型(即自定义类,甚至std::string),那么 usingstd::move可以为您提供很好的性能提升,因为它可以避免复制构造函数。但是,对于向量int,它不会给您带来任何好处。

注意 2:值得一提的是,使用std::move会导致您的 sourcevector的内容无法使用。

于 2013-08-09T13:16:12.577 回答
20

假设您要复制而不是移动,这将是最好的方法:

a.reserve(a.size()+b.size()+c.size()); // Reserve space first
a.insert(a.end(),b.begin(),b.end());
a.insert(a.end(),c.begin(),c.end());

如果你想搬家:

a.reserve(a.size()+b.size()+c.size()); // Reserve space first
a.insert(a.end(),std::make_move_iterator(b.begin()),
         std::make_move_iterator(b.end()));
a.insert(a.end(),std::make_move_iterator(c.begin()),
         std::make_move_iterator(c.end()));
b.swap(std::vector<int>()); // Clear and deallocate space
c.swap(std::vector<int>()); // Clear and deallocate space

更新:您现在已经多次编辑您的问题,使其成为一个移动目标。您的第一个选项现在与我的第一个建议非常相似。

更新 2:从 C++11 开始,您可能不再需要使用“与空向量交换”技巧来清除和释放空间,具体取决于您的库的vector. 以下可能以更直观的方式完成工作:

// Empty the vectors of objects
b.clear(); 
c.clear();

// Deallocate the memory allocated by the vectors 
// Note: Unlike the swap trick, this is non-binding and any space reduction
//       depends on the implementation of std::vector
b.shrink_to_fit();
c.shrink_to_fit();
于 2013-08-09T13:12:50.860 回答
1

第一个是最好的选择,因为insert可以在开始复制之前计算出它添加了多少元素并调整向量的大小以适应它。其他人没有该信息,因此可能会在一些复制后最终调整大小,这比开始调整大小或多次调整大小要慢。

但是,正如@michaelgoldshteyn 所暗示的那样,由于您要进行两次插入,因此您也可以自己调整数组的最终大小,从而可能节省一次调整大小。

于 2013-08-09T13:13:49.520 回答
0

如果您真的想在 vector中附加band的数据,则必须进行插入(实际上是您的1.):ca

a.reserve( a.size() + b.size() + c.size() ); // preallocate memory (see why)
a.insert( a.end(), b.begin(), b.end() );
a.insert( a.end(), c.begin(), c.end() );

取决于编译器std::copy(你的2.)通常应该一样快。

由于 astd::vector在内存中必须始终是连续的,因此您不能只移动(如 C++11 中定义的那样),并且如果您知道最终大小,则必须保留向量(这将避免不必要的向量重新分配)。但是,如果您真的担心性能,请将其设为三个std::vector,并在您必须读取它们的数据时对其进行迭代。

于 2013-08-09T13:17:09.587 回答