【问题标题】:How were move semantics addressed before C++11?在 C++11 之前如何处理移动语义?
【发布时间】:2016-12-08 04:06:54
【问题描述】:

我最近一直在阅读移动语义以及它是如何被引入 C++11 的。主要要点是,通过“窃取”指向临时对象的指针来创建对象,程序可以变得更有效率。这比对临时对象进行深度复制以创建新对象要高效得多。

在 C++11(及更高版本)中,这是通过使用右值引用来实现的。所有临时对象(在程序内存中没有已知位置的对象)都被视为右值。具体来说,现在可以重载类构造函数以接受右值引用。

所以我很好奇,在 C++11 之前,这个“昂贵的临时对象复制”问题是如何解决的?

【问题讨论】:

  • 谷歌“写时复制”。
  • 我想说,您更喜欢新版本 C++ 的动态特性,而不必担心过去。 :P
  • 然后您会发现自己的项目仍然绑定到 GCC 3.3,因为这是您维护的硬件可用的最新编译器。很高兴知道一些历史,所以你不必重复它。或者在这种情况下,你可以重复它而无需几周的研究

标签: c++ c++03


【解决方案1】:

完成此操作的主要方式是通过std::swapstd::swap 可以重载/专门用于可以比默认的“通过临时变量交换”更有效地执行的类型,而不是执行浅交换。

通常数据类型会提供一个swap() 成员函数,此重载可以使用该成员函数来访问数据类型的私有内部。 (例如;见std::vector::swap

例如;要将元素“移动”到vector,可以使用以下代码:

class MyListOfVectors {
    private:
    //using `std::vector<int>` as an example of a "movable" type.
    std::vector<std::vector<int>> list;
    public:
    void emplace_back(std::vector<int> &n) {
        using std::swap;
        list.push_back(std::vector<int>());
        swap(list.back(), n);
        //(possibly add something to rollback the `push`
        // in case swap fails; to provide the strong
        // exception guarantee)
    }
};

要通过“移动”返回一个元素,可以使用以下代码:

std::vector<int> MyListOfVectors::pop_back() {
    using std::swap;
    std::vector<int> r;
    swap(list.back(), r);
    list.pop_back();
    return r; //Trust in copy elision to avoid any actual copies.
}

我没有这方面的参考,但我相信标准算法被允许/鼓励为此目的使用std::swap

另外,如果你觉得你想以 C++11 的方式做事,你也可以使用 boost::move,它提供了 C++03 中 C++11 移动语义的模拟(尽管它技术上违反了严格的别名,因此具有未定义的行为)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-30
    • 2014-08-16
    • 2019-01-02
    • 2014-03-18
    • 2023-03-26
    • 2012-12-10
    相关资源
    最近更新 更多