【问题标题】:"move" two vectors together一起“移动”两个向量
【发布时间】:2012-04-04 09:57:02
【问题描述】:

如果我有两个向量并且想将它们组合为一个,我可以通过以下方式进行:

std::vector<T> a(100); // just some random size here
std::vector<T> b(100);

a.insert(std::end(a), std::begin(b), std::end(b));

不过,这涉及到复制,我想避免这种情况。有没有办法使用移动语义将它们组合在一起?
我非常怀疑它,因为vector 应该是连续的。但是有什么办法可以用deque 做到这一点?

【问题讨论】:

    标签: c++ vector c++11 move deque


    【解决方案1】:

    是的,使用std::move

    #include <algorithm>
    std::move(b.begin(), b.end(), std::back_inserter(a));
    

    或者,您可以使用移动迭代器:

    a.insert(a.end(),
             std::make_move_iterator(b.begin()), std::make_move_iterator(b.end()));
    

    在这两种情况下都记得#include &lt;iterator&gt;,在你开始之前,说:

    a.reserve(a.size() + b.size());
    

    根据值初始化与检查和增加大小计数器相比的成本,以下变体可能也很有趣:

    std::size_t n = a.size();
    a.resize(a.size() + b.size());
    std::move(b.begin(), b.end(), a.begin() + n);
    

    【讨论】:

    • 谢谢,现在我知道为什么 cppreference 上有两个版本的std::move。我一直认为这是一个错误,并没有检查第二个版本。
    • 我完全错过了move 也是一种算法。
    • @bames53 我也遇到过同样的情况,但听了之后觉得很有道理,因为还有copy
    • @mustafabar: std::vector 保证连续存储。实际上,这可能需要重新分配。一般来说,如果不以某种方式复制一些内存内容,就无法神奇地将内存的两个独立部分变成一个连续的部分。
    • @KerrekSB,没错。我试图在这里理解。所以使用“移动范围”的好处是节点不会被重建,它们宁愿被移动,源向量指针会失效?而如果你使用“移动构造函数”,就没有新分配的记忆在此之上
    【解决方案2】:

    具体取决于您要移动的内容。当你移动一个向量时,它是通过有效地交换内部数组指针来完成的。因此,您可以使一个向量指向先前由另一个向量拥有的数组。

    但这不会让你合并两个向量。

    那么你能做的最好的就是移动每个单独的成员元素,如 Kerrek 的回答所示:

    std::move(b.begin(), b.end(), std::back_inserter(a));
    

    同样,这将遍历向量并将每个元素移动到目标向量。

    【讨论】:

    • 一个问题,但它有什么不同?我们本质上不是将 a 中的对象复制到 b 的位置吗?它不会和操作问题中的 insert 做同样的事情吗?
    • 我想如果 a 中的对象很复杂,那么它们的复制 ctor 将不会被调用,只是一个内存副本?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-13
    • 2019-11-20
    • 2022-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多