0
struct F
{
private:
    int* data;

public:
    F( int n ) 
    { 
        data = new int; 
        *data = n; 
    }

    F( int* p ) 
    { 
        data = p; 
    }

    F& operator=( const F& f ) 
    { 
        *data = *(f.get_data()); 
        return *this; 
    }

    F& operator=( F&& f ) 
    {
        delete data;
        data = f.data;
        f.data = nullptr;
        return *this;
    }

    F& operator=( int n ) { *data = n; return *this; }

    F operator()() 
    {
        F cpy_f( data );
        return std::move( cpy_f );
    }

    int* get_data() const { return data; }
};

int main()
{
    F f( 12 );
    F g( 14 );
    f() = g();
    cout << *(f.get_data()) << endl;
}

この例では、f()とはg()それぞれ一時オブジェクトを返すため、一時オブジェクトf()=g()の式は一時オブジェクトと等しくなります。値が正しくコピーされていれば、答えは14だと思っていたでしょう。ただし、コピー代入はなく、ムーブ代入を呼び出します。結果として、答えは14ではありません。

これは私を本当に混乱させます。から返されるオブジェクトは一時f()g()なものですが、他のオブジェクトと情報を共有しています。これは、一時オブジェクトが共有情報に対してまもなくいくつかの作業を実行する可能性があることを意味します。したがって、意味的にコピー割り当てを呼び出すことが正しい動作であると思われます。

ps。私のコンパイラはg++4.720110430です

4

2 に答える 2

4

参照やポインターoperator()ではなく、値を返します。したがって、一時を返します。一時変数は暗黙的に && に優先的にバインドします (そうする唯一の型です)。したがって、使用するムーブ代入演算子があれば、それを使用することを好みます。

あなたの問題は、operator()関数でこれを行ったときに合理的なことをやめたことです:

F cpy_f( data );

ポインターを取るコンストラクターはF、ポインター値自体を使用して、ポインターを効果的に採用します。その時点で、同じデータを指す2 つのインスタンスができています。 F

それが合理的になりたい場合は、移動代入演算子でポインターを削除することはできません。F同じものを指す2 つのインスタンスを持つことができるという事実を調整する必要があります。2 つはポインタの所有権を共有する必要があります。それで...どうやってそれをするつもりですか?

このコンストラクターを完全に削除することをお勧めします。それはあなたにとってより多くの問題を生み出すだけです。std::unique_ptr<int> data;また、ネイキッド ポインターの代わりに aを使用することをお勧めします。そうすれば、移動コンストラクター/代入演算子を記述する必要はありません (ただし、コピー コンストラクター/代入演算子は必要です)。

于 2012-02-02T05:52:12.593 に答える
0

同じ場所を指すポインターを持つインスタンスを作成しています。で作成されたインスタンスは、ポインター自体を共有しF::operator()ません。

f()=g()は f().operator=(g()) と同等でg()、一時的なインスタンスを作成するため、move 代入を呼び出すのが正しいです。

問題はf、 の実行後にダングリング ポインターがあることですf()=g()f()一時インスタンスを作成し、移動代入演算子のポインターを削除しますが、fそれ自体には削除された場所を指すポインターがまだあります。

複雑なコードで何をしているのかわかりませんが、コードをstd::shared_ptr何かで書き直した方がよいでしょう。

std::movepsインスタンスを返す必要はありません。これらをオフにしていない場合、コンパイラには RVO 機能があります。

于 2012-02-02T05:46:12.367 に答える