在C++ 11中移动语义

RuL*_*ViC 0 c++ operators move-constructor move-semantics c++11

我想完全理解C++ 11中的移动语义.所以我编写了几个类来查看何时调用不同的构造函数:

#include <iostream>
using namespace std;

class A {
public:
    A() : a1_(0) {std::cout << "Calling constructor" << std::endl;}
    A(A&& other) {
        std::cout << "Calling move constructor" << std::endl;
        a1_ = other.a1_;
        other.a1_ = 0;
    }

    // Move assignment operator.
    A& operator=(A&& other) {
        std::cout << "Calling move operator" << std::endl;
        if (this != &other) {
            a1_ = other.a1_;
            other.a1_ = 0;
        }
        return *this;
    }

    // Copy constructor.
    A(const A& other) {
        std::cout << "Calling copy constructor" << std::endl;
        a1_ = other.a1_;
    }

    // Copy assignment operator.
    A& operator=(const A& other) {
        std::cout << "Calling copy assignment operator" << std::endl;
        if (this != &other) {
            a1_ = other.a1_;
        }
        return *this;
    }

private:
    int a1_;
};

class B {
    A oA_;

public:
    B() {}
    void setoA(A a) {oA_ = a;}
        A getoA() {return oA_;}
};

A createA() {
    A a1;
    return a1;
}

B createB() {
    B tmpB;
    A tmpA;
    tmpB.setoA(tmpA);
    return tmpB;
}

int main() {
    B b;
    A a;
    b.setoA(a);
    std::cout << "**************************" << std::endl;
    b.setoA(createA());
    std::cout << "**************************" << std::endl;
    b.setoA(std::move(createA()));
    std::cout << "**************************" << std::endl;
    B b2;
    b2.setoA(b.getoA());
    std::cout << "**************************" << std::endl;
    createB();

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

当我检查此代码的输出时:

    Calling constructor

    Calling constructor

    Calling copy constructor

    Calling copy assignment operator

    ++++++++++++++++++++++++++++++++++

    Calling constructor

    Calling copy assignment operator

    ++++++++++++++++++++++++++++++++++

    Calling constructor

    Calling move constructor

    Calling copy assignment operator

    ++++++++++++++++++++++++++++++++++

    Calling constructor

    Calling copy constructor

    Calling copy assignment operator

    ++++++++++++++++++++++++++++++++++

    Calling constructor

    Calling constructor

    Calling copy constructor

    Calling copy assignment operator

我在这里有些疑惑:

我以为如果你通过r-value,移动构造函数会被调用,是吗?这难道不是b.setoA(createA());一个r-value

如何调用移动构造函数/运算符?

Aco*_*gua 6

首先,在第一节中,为什么构造函数被调用两次?

因为你构造了一个B和一个A前者有自己的实例A,第一个(意外的)构造函数调用来自.

我以为如果你传递r值移动构造函数会被调用,是吗?这不是b.setoA(createA());一个r值吗?

构造函数从内部调用createA(是的,返回值一个r值),但是,会发生复制省略,并且对象直接在参数变量of中实例化setoA.

setoA但是,在内部,选择了复制分配,因为现在a是l值.如果你想搬家,你需要:

void setoA(A a) { oA_ = std::move(a); }
Run Code Online (Sandbox Code Playgroud)