关于c ++:将向量追加到向量的最佳方法

Best way to append vector to vector

本问题已经有最佳答案,请猛点这里访问。
1
2
3
std::vector<int> a;
std::vector<int> b;
std::vector<int> c;

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

1)使用vector::insert

1
2
3
4
5
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

1
2
3
4
5
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):

1
2
3
4
5
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();


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

vector<>::insert是为添加元素而设计的,因此它是最合适的解决方案。

你可以在目的地向量上调用reserve来保留一些空间,但是除非你把很多向量加在一起,否则它可能不会提供很多好处:vector<>::insert知道要添加多少元素,你只会避免一个reserve调用。

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

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


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

1
2
3
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());

如果你想搬家:

1
2
3
4
5
6
7
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,您可能不再需要使用"空向量交换"技巧来清除和释放空间,这取决于库的EDOCX1×0的实现。以下可能以更直观的方式完成工作:

1
2
3
4
5
6
7
8
9
// 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();


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

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


如果你真的想在矢量a中附加bc的数据,你就必须进行插入(实际上是你的1):

1
2
3
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)通常应该同样快。

因为EDCOX1的16位总是在内存中是连续的,所以不能仅仅移动(如C++ 11中定义的),如果你知道最终的大小,你必须保留你的向量(它将避免向量的不必要的重新分配)。但是,如果您真的担心性能,那么就让它作为3个std::vector,并在必须读取它们的数据时对它们进行迭代。