2
struct Test
{
    Test()
    {}

    Test(const Test& other)
    {
        cout << "Copy" << endl;
    }

    Test(Test&& other)  
    {
        cout << "Move" << endl;
    }
};

Test* f()
{
    static Test t;
    return &t;
}

int main()
{   
    auto t = *f();
    return 0;
}

出力:コピー

*f()は明らかに匿名の一時オブジェクトであるため、r 値である必要があり、move-constructor を呼び出す必要があります。コンパイラが左辺値として扱うのはなぜ*f()ですか?

コンパイラのバグなのか、私の理解が間違っているのでしょうか。

4

5 に答える 5

14

の結果f()は、タイプ の無名の一時オブジェクトですTest*f()右辺値です。

*f()上記のポインターを介して間接化を実行します。間接演算子を使用する場合は常にそうであるように、結果は左辺値です。

于 2012-05-18T17:04:27.763 に答える
8

コンパイラが *f() を左辺値として扱うのはなぜですか?

左辺値だからです。ポインターに適用されたときの operator* の結果は、常に左辺値です。また、左辺値から暗黙的に移動することはできません。

移動に関する黄金律を覚えておいてください。移動は、安全であることが保証されている場合にのみ発生します (「保証された」という特定の定義について)。

コードを見てください。移動元のオブジェクトが破棄され、移動後にアクセスできなくなることは明らかですか? そうでない場合は、 を使用してそこから移動する必要があります。std::moveこれにより、動きが原因で発生するすべての障害に対して責任を負うことをシステムに伝えます。

于 2012-05-18T17:04:10.080 に答える
3

実際には、の戻り値f()はポインターです。ポインターを逆参照しても、新しいオブジェクトが発生することはありません。ただし、戻り値が指すメモリアドレスにあるものは何でも にコピーしていますt。この場合、私は確かにコピーを期待します。

于 2012-05-18T17:03:12.873 に答える
1

「*f() は明らかに匿名の一時オブジェクトです...」

いいえ、ちがいます!静的オブジェクトです。

于 2012-05-18T17:00:55.450 に答える
0
Test f()
{
    return Test();
}

int main()
{   
    auto t = f();
    return 0;
}

、あなたは匿名の一時的なものを返しています - 手がかりは、一時的なものを作成し、それを名前にバインドせずに値で返すことです。

他の誰もが正しく指摘したように、あなたがしていることは、静的な(一時的ではない)名前付き(匿名ではない)オブジェクトへのポインタを返すことです。ポインターは匿名の一時的なものである可能性がありますが、それが指すものそうではありません。

于 2012-05-18T17:08:19.817 に答える