簡體   English   中英

在C ++ 11中移動語義

[英]Move semantics in 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;
}

當我檢查此代碼的輸出時:

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 ,就會調用move構造函數,對嗎? 這不是b.setoA(createA()); r-value

如何使移動構造函數/運算符被調用?

首先在第一節中,為什么構造函數被調用兩次?

因為你既構建一個BA與前者有其自身的實例A ,其中第(意外)構造函數調用的來源。

我以為如果通過r值將調用move構造函數,對嗎? 這不是b.setoA(createA()); 一個r值?

構造函數是在createA (是的,返回值一個r值),但是,會發生復制省略,並且直接在setoA的參數變量中實例化該對象。

但是,在setoA中選擇了副本分配,因為現在a是一個l值。 如果要移動,則需要:

void setoA(A a) { oA_ = std::move(a); }

編譯器可以選擇刪除某些副本和移動。 為防止這種情況,請在GCC和Clang中使用-fno-elide-constructors 另外,一些移動省略在C ++ 17中成為強制性的,因此要強制編譯器使用C ++ 11移動語義, -std=c++11使用-std=c++11

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM