有没有将范围移动到矢量的标准方法?

时间:2012-05-23 12:41:18

标签: c++ c++11 insert stdvector

考虑以下程序,将一系列元素插入到矢量中:

vector<string> v1;
vector<string> v2;

v1.push_back("one");
v1.push_back("two");
v1.push_back("three");

v2.push_back("four");
v2.push_back("five");
v2.push_back("six");

v1.insert(v1.end(), v2.begin(), v2.end());

这有效地复制了范围,在整个范围内为目标矢量分配了足够的空间,因此最多需要一个调整大小。现在考虑以下程序尝试将范围移动到向量中:

vector<string> v1;
vector<string> v2;

v1.push_back("one");
v1.push_back("two");
v1.push_back("three");

v2.push_back("four");
v2.push_back("five");
v2.push_back("six");

for_each ( v2.begin(), v2.end(), [&v1]( string & s )
{
    v1.emplace_back(std::move(s));
});

这会执行成功的移动但不会享受insert()在目标向量中预分配空间方面的优势,因此在操作期间可以多次调整向量的大小。

所以我的问题是,是否存在可以将范围移动到向量中的插入等效项?

2 个答案:

答案 0 :(得分:78)

您使用move_iteratorinsert

v1.insert(v1.end(), make_move_iterator(v2.begin()), make_move_iterator(v2.end()));

24.5.3中的例子几乎就是这个。

如果(a)vector::insert使用iterator-tag dispatch来检测随机访问迭代器并预先计算大小(您假设它在您的示例中复制了),您将获得所需的优化,和(b)move_iterator保留它包装的迭代器的迭代器类别(这是标准所要求的)。

在一个模糊的观点上:我很确定vector::insert可以从源(这在此处无关紧要),因为源与目的地的类型相同,因此一个emplace与副本相同/ move,但与其他相同的例子相关)。我还没有发现需要这样做的声明,我只是通过传递给i,j的迭代器对insert的要求是T的事实推断出来的。来自EmplaceConstructible的{​​{1}}。

答案 1 :(得分:33)

    具有预分配的
  1. std::move算法:

    #include <iterator>
    #include <algorithm>
    
    v1.reserve(v1.size() + v2.size()); // optional
    std::move(v2.begin(), v2.end(), std::back_inserter(v1));
    
  2. 以下内容会更加灵活:

    v1.insert(v1.end(), 
         std::make_move_iterator(v2.begin()), 
         std::make_move_iterator(v2.end()));
    

    Steve Jessop提供了有关它的确切内容的背景信息,以及它是如何做到的。