将矢量追加到矢量的最佳方法

时间:2013-08-09 13:09:05

标签: c++ c++11 vector append std

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

我想通过将bc的元素附加到a来连接这三个向量。这是最好的方法,为什么?


1)使用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)使用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)使用std::move(来自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 个答案:

答案 0 :(得分:24)

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

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

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

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

注释2 :值得一提的是,使用std::move会导致源vector的内容无法使用。

答案 1 :(得分:19)

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

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();

答案 2 :(得分:1)

第一个是最佳选择,因为insert可以计算出它添加的元素数量,并在开始复制之前调整矢量大小。其他人没有这些信息,所以最终可能会在复制后调整大小,这比在开始时调整大小或调整大小不止一次。

然而,正如@michaelgoldshteyn暗示的那样,既然你要进行两次插入,你也可以自己调整最终大小的数组,可能会节省一次调整大小。

答案 3 :(得分:0)

如果你真的想在向量b中追加ca的数据,你必须进行插入(实际上是你的 1。 ):

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。)通常应该一样快。

由于std::vector在内存中始终是连续的,因此您不能只是移动(如C ++ 11中所定义)并且如果您知道结束大小你必须保留你的矢量(这将避免不必要的矢量重新分配)。但是如果你真的担心性能问题,那就把它当作三个std::vector并在你必须阅读它们的数据时迭代它们。