C++ 有没有一种标准的方法将一个范围移动到一个向量中?

C++ 有没有一种标准的方法将一个范围移动到一个向量中?,c++,c++11,insert,stdvector,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()); vect

考虑以下将一系列元素插入向量的程序:

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));
});
向量v1;
矢量v2;
v1.推回(“一”);
v1.推回(“两”);
v1.向后推(“三”);
v2.推回(“四”);
v2.向后推(“五”);
v2.向后推(“六”);
插入(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");

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));
});
向量v1;
矢量v2;
v1.推回(“一”);
v1.推回(“两”);
v1.向后推(“三”);
v2.推回(“四”);
v2.向后推(“五”);
v2.向后推(“六”);
对于每个(v2.begin()、v2.end()、[&v1](字符串和字符串)
{
v1.向后安放(标准:移动);
});
这执行了成功的移动,但没有享受insert()在目标向量中预分配空间方面的好处,因此在操作过程中可以多次调整向量的大小

所以我的问题是,是否有一个插入等价物可以将一个范围移动到一个向量中

  • 带预分配的算法:

    #include <iterator>
    #include <algorithm>
    
    v1.reserve(v1.size() + v2.size()); // optional
    std::move(v2.begin(), v2.end(), std::back_inserter(v1));
    
    史蒂夫·杰索普(Steve Jessop)提供了确切的背景信息,说明了它的作用以及可能的作用方式


  • 移动迭代器
    插入一起使用

    v1.insert(v1.end(), make_move_iterator(v2.begin()), make_move_iterator(v2.end()));
    
    24.5.3中的示例几乎就是这样

    如果(a)
    vector::insert
    使用迭代器标记分派来检测随机访问迭代器并预计算其大小(您在示例中假设它会复制),以及(b)
    move\u迭代器
    保留其包装的迭代器的迭代器类别,您将获得所需的优化(这是标准要求的)


    有一点不太清楚:我很确定
    vector::insert
    可以从源位置放置(这在这里是不相关的,因为源位置与目标位置的类型相同,所以放置位置与复制/移动位置相同,但与其他相同的示例相关).我还没有找到这样做所需的语句,我只是根据传递给
    insert
    的迭代器对
    I,j
    的要求是
    t
    be
    EmplaceConstructible
    from
    *I

    如果需要在向量中预先分配空间,请使用
    std::vector::reserve
    ,并保持
    向后推
    /
    向后放置
    。这将是一个可选的优化,只有当范围由随机访问迭代器定义时才可能。不要指望它。@rubenvb是的,我想这可能是答案,可惜没有一个方法像
    insert()那样干净
    是。尽管使用
    std::vector
    no时总是这样?@Benj:
    std::vector
    迭代器是随机访问的,但库可能不包括优化。问题似乎是关于从任意未指定范围插入向量,该范围可能没有随机访问迭代器只调整一次目标
    vector
    的大小非常小。哦,奈特,我不知道这种形式的
    std::move
    。虽然我猜
    back\u inserter
    仍然会导致多次调整大小。@BenVoigt为什么?我想这取决于实现。vector::reserve是你的朋友。让我检查一下标准。@sehe:
    back\u inserter
    不知道它将被调用多少次。
    std::move
    可以发现,但它无法知道目标插入到向量中。我认为第一个插入器实际上只能重新分配一次:
    move
    可以看到您有一个随机访问迭代器,所以我t可以计算出所需的大小,但它只看到一个
    back\u insert\u迭代器
    ,而不是底层向量,因此它无法保留空间。它需要异常曲折的
    std::move
    重载才能捕捉到这种情况。很好,我不知道
    make\u move\u迭代器
    嗯,我发现这也是可能的使用
    make_move_iterator
    std::copy_if
    转换为
    std::move_if
    的等价物。这非常方便。很抱歉重新启动此功能,并在注释中提出问题,但如果源向量和目标向量是向量,该怎么办?在第一个参数上应用make_move_iterator将不起作用,如果没有它,将产生一个e关于复制加薪的错误。我该怎么做?@Evgeny:对我有效,所以我可能误解了你的意思。我建议你问一个新问题,包括对你无效的代码。@EvgenyDanilenko:是的,一个
    const unique_ptr
    非常棘手。无法复制也无法移动它。恐怕它会被引用到坟墓里去,尽管我可能错过了一些聪明的把戏。