我应该如何拼接两个std::vector
?
vector1.insert( vector1.end(), vector2.begin(), vector2.end() );
vector1.capacity() >= 2 * vector1.size()
时才能这样做。这种情况并不常见,除非你已经调用了 std::vector::reserve()
。否则,向量将进行重新分配,从而使参数2和3所传递的迭代器无效。 - Drew Dormann.concat
或+=
或其他什么东西。 - nmr如果你正在使用C++11,并且希望移动元素而不仅仅是复制它们,你可以使用std::move_iterator
与insert(或copy)一起使用:
#include <vector>
#include <iostream>
#include <iterator>
int main(int argc, char** argv) {
std::vector<int> dest{1,2,3,4,5};
std::vector<int> src{6,7,8,9,10};
// Move elements from src to dest.
// src is left in undefined but safe-to-destruct state.
dest.insert(
dest.end(),
std::make_move_iterator(src.begin()),
std::make_move_iterator(src.end())
);
// Print out concatenated vector.
std::copy(
dest.begin(),
dest.end(),
std::ostream_iterator<int>(std::cout, "\n")
);
return 0;
}
对于整数示例而言,这样做并不会更加高效,因为移动它们的效率与复制它们相同,但是对于已优化移动的数据结构,它可以避免复制不必要的状态:
#include <vector>
#include <iostream>
#include <iterator>
int main(int argc, char** argv) {
std::vector<std::vector<int>> dest{{1,2,3,4,5}, {3,4}};
std::vector<std::vector<int>> src{{6,7,8,9,10}};
// Move elements from src to dest.
// src is left in undefined but safe-to-destruct state.
dest.insert(
dest.end(),
std::make_move_iterator(src.begin()),
std::make_move_iterator(src.end())
);
return 0;
}
在移动完成后,src元素处于未定义但安全销毁状态,其以前的元素直接转移到dest的新元素末尾。std::move(src.begin(), src.end(), back_inserter(dest))
有什么不同? - kshenoyinsert
可能一次性分配所需的内存。而 back_inserter
则可能导致多次重新分配。 - yrHeTateJlbstd::make_move_iterator()
有什么区别? - road_to_quantdom我会使用insert函数,类似这样:
vector<int> a, b;
//fill with data
b.insert(b.end(), a.begin(), a.end());
或者您可以使用:
std::copy(source.begin(), source.end(), std::back_inserter(destination));
如果两个向量包含的内容不完全相同,那么这种模式是有用的,因为您可以使用某些东西代替 std::back_inserter
将一种类型转换为另一种类型。
reserve
方法。使用 std::copy
的原因在于如果你想使用除了 back_inserter
以外的其他方式时,它就会变得很有用。 - Roger Lipscombemove_iterator
的insert()
有何不同?如果有,具体是什么? - GPhilostd::move
的注释,因为大多数人不知道这个重载。希望这是一个改进。 - YSCstd::vector<int> first;
std::vector<int> second;
first.insert(first.end(), second.begin(), second.end());
我更喜欢已经提到的那一个:
a.insert(a.end(), b.begin(), b.end());
但如果您使用C++11,还有一种更通用的方法:
a.insert(std::end(a), std::begin(b), std::end(b));
此外,虽然不是问题的一部分,但建议在追加之前使用reserve
以获得更好的性能。如果您将向量与自身连接而没有保留空间,则操作将失败,因此您应始终reserve
。
所以基本上你需要:
template <typename T>
void Append(std::vector<T>& a, const std::vector<T>& b)
{
a.reserve(a.size() + b.size());
a.insert(a.end(), b.begin(), b.end());
}
a
的类型来自于std
,那么ADL
只会添加std::
,这将破坏泛型的特性。 - Potatoswatterinsert
将向量连接到自身是超出insert
规范的(未定义行为)。提前调用reserve
也无法改变这一点。 - j6t提高concatenate的性能的一般方法是检查向量的大小,并将较小的向量与较大的向量合并/插入。
//vector<int> v1,v2;
if(v1.size()>v2.size()) {
v1.insert(v1.end(),v2.begin(),v2.end());
} else {
v2.insert(v2.end(),v1.begin(),v1.end());
}
v1.insert(v2.end()...)
使用了一个指向v2
的迭代器来指定在v1
中的位置。 - David Stone在C++17中,有一个算法std::merge
,当输入向量已排序时非常易于使用。
以下是示例:
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
//DATA
std::vector<int> v1{2,4,6,8};
std::vector<int> v2{12,14,16,18};
//MERGE
std::vector<int> dst;
std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(dst));
//PRINT
for(auto item:dst)
std::cout<<item<<" ";
return 0;
}
std::vector::insert
更容易使用,但它确实做了一些不同的事情:将两个范围合并成一个新范围,而不是将一个向量插入到另一个末尾。这值得在答案中提到吗? - j b
a + b
或a.concat(b)
的人吗?也许默认实现会不够优化,但并不需要对每个数组连接都进行微观优化。 - oseiskarforceVector1 + forceVector2
,以便在清晰简明的代码中进行逐项加法。 - Jonathan Lidbeck