4

私は C++11 を勉強していますが、次のコードの理由がわかりません

class X
{
    std::vector<double> data;
public:
    // Constructor1
    X():
        data(100000) // lots of data
    {}

    // Constructor2
    X(X const& other): // copy constructor
        data(other.data)   // duplicate all that data
    {}

    // Constructor3
    X(X&& other):  // move constructor
        data(std::move(other.data)) // move the data: no copies
    {}

    X& operator=(X const& other) // copy-assignment
    {
        data=other.data; // copy all the data
        return *this;
    }

    X& operator=(X && other) // move-assignment
    {
        data=std::move(other.data); // move the data: no copies
        return *this;
    }

};

X make_x() // build an X with some data
{
    X myNewObject; // Constructor1 gets called here
    // fill data..
    return myNewObject; // Constructor3 gets called here
}


int main()
{
    X x1;
    X x2(x1); // copy
    X x3(std::move(x1)); // move: x1 no longer has any data

    x1=make_x(); // return value is an rvalue, so move rather than copy
}

ラインで

return myNewObject; // Constructor3 gets called here

Constructor3 が呼び出されます。なんで?

4

2 に答える 2

3

コンパイラが標準で許可されているすべての最適化を行っていないため、move コンストラクションが表示されます。

名目上、変数myNewObjectは の戻り値であるテンポラリにムーブ構築され、make_x次にテンポラリが にムーブ代入されx1ます。これはあなたが見ているものです。

ただし、この場合、標準では「コンストラクターの移動省略」と呼ばれるものが許可されています。これは、C++03 でおなじみかもしれない「コピー コンストラクターの省略」と基本的に同じことです。これは、変数myNewObjectと戻り値である一時make_xオブジェクトをコンパイラによって単一のオブジェクトに変換できることを意味します。これで移動の割り当てだけが残ります。

どうやらあなたのコンパイラは移動省略を行っていません。

コピーを予期していた場合、それが移動である理由は、C++11 では、コピー省略の対象となる戻り値 (これはこれです) は、移動が可能な場合にコピーするのではなく、移動する必要があるためです。 . 参考文献を思い出せませんし、標準も手元にないので、私の言葉を信じてください。

于 2013-03-30T13:18:53.680 に答える
1
X make_x() // build an X with some data
{
    X myNewObject; // Constructor1 gets called here
    // fill data..
    return myNewObject; // Constructor3 gets called here
}

myNewObjectこの関数スコープの最後で破棄されるため、コンパイラーが移動して内臓を引き裂いても問題ありません。

于 2013-03-30T12:31:38.320 に答える