C++ 移动构造函数

示例

假设我们有此代码段。

class A {
public:
    int a;
    int b;
       
    A(const A &other) {
        this->a = other.a;
        this->b = other.b;
    }
};

要创建一个复制构造函数,即创建一个复制一个对象并创建一个新对象的函数,我们通常会选择上面显示的语法,我们将为A提供一个构造函数,该构造函数将引用另一个类型为A的对象,我们将在方法内部手动复制对象。

或者,我们可以编写A(const A &) = default;使用它的副本构造函数自动复制所有成员的代码。

但是,要创建一个移动构造函数,我们将采用一个右值引用而不是一个左值引用,就像这里一样。

class Wallet {
public:
    int nrOfDollars;
    
    Wallet() = default; //默认ctor

    Wallet(Wallet &&other) {
        this->nrOfDollars = other.nrOfDollars;
       other.nrOfDollars= 0;
    }
};

请注意,我们将旧值设置为zero。默认的move构造函数(Wallet(Wallet&&) = default;)复制PO的值nrOfDollars。

由于移动语义旨在允许从原始实例“窃取”状态,因此重要的是考虑这种窃取后原始实例的外观。在这种情况下,如果我们不将值更改为零,我们将使美元数量增加一倍。

Wallet a;
a.nrOfDollars = 1;
Wallet b (std::move(a)); //calling B(B&& other);
std::cout <<a.nrOfDollars<< std::endl; //0
std::cout <<b.nrOfDollars<< std::endl; //1

因此,我们从一个旧的对象开始构造一个对象。


尽管上面是一个简单的示例,但它显示了move构造函数打算做什么。它在更复杂的情况下(如涉及资源管理)变得更加有用。

    // 管理涉及指定类型的操作。
    // 在堆上拥有一个助手,并在其内存中拥有一个(大概在堆栈上)。
    // 这两个助手都是DefaultConstructible,CopyConstructible和MoveConstructible。
    template<typename T,
             template<typename> typename HeapHelper,
             template<typename> typename StackHelper>
    class OperationsManager {
        using MyType = OperationsManager<T, HeapHelper, StackHelper>;

        HeapHelper<T>* h_helper;
        StackHelper<T> s_helper;
        // ...

      public:
        // Default constructor & Rule of Five.
        OperationsManager() : h_helper(new HeapHelper<T>) {}
        OperationsManager(const MyType& other)
          : h_helper(new HeapHelper<T>(*other.h_helper)), s_helper(other.s_helper) {}
        MyType& operator=(MyType copy) {
            swap(*this, copy);
            return *this;
        }
        ~OperationsManager() {
            if (h_helper) { delete h_helper; }
        }

        // 移动构造函数(不包含swap())。
        // Takes other's HeapHelper<T>*.
        // Takes other's StackHelper<T>, by forcing the use of StackHelper<T>'s move constructor.
        // Replaces other's HeapHelper<T>* with nullptr, to keep other from deleting our shiny
        //  销毁时的新帮手。
        OperationsManager(MyType&& other) noexcept
          : h_helper(other.h_helper),
            s_helper(std::move(other.s_helper)) {
           other.h_helper= nullptr;
        }

        // 移动构造函数(使用swap())。
        // 将我们的成员置于我们希望他人处于的状态,然后切换成员
        //  和其他人。
        // OperationsManager(MyType&& other) noexcept : h_helper(nullptr) {
        //     swap(* this,other);
        // }

        // 复制/移动助手。
        friend void swap(MyType& left, MyType& right) noexcept {
            std::swap(left.h_helper, right.h_helper);
            std::swap(left.s_helper, right.s_helper);
        }
    };