3

重複の可能性:
移動元のオブジェクトで何ができますか?

たとえば、次のコードを参照してください。

template<class T> 
void swap(T& a, T& b) 
{ 
    T tmp(std::move(a));
    a = std::move(b); 
    b = std::move(tmp);
} 

それは私だけですか、それともここにバグがありますか?あなたがmove aに入るならtmp、それからa無効になりませんか?

つまり、move-assignmentをafrombに配置して、move-constructor呼び出しにするべきではありませんnewか?
そうでない場合、ムーブコンストラクタとムーブ代入演算子の違いは何ですか?

template<class T>
void swap(T& a, T& b)
{
    T tmp(std::move(a));
    new(&a) T(std::move(b));
    new(&b) T(std::move(tmp));
}
4

3 に答える 3

10

オブジェクトからデータを移動する場合、意図されたセマンティクスは、移動元のオブジェクトが指定されていないが有効な状態になることです。つまり、オブジェクトが整形式のオブジェクトになることを除いて、オブジェクトがどのような状態になるかについては何も予測できません。これは、「このオブジェクトは死んでしまった」とはまったく同じではありません。オブジェクトからデータを移動しても、オブジェクトの存続期間は終了しません。つまり、状態が指定されていないものに変更されるだけです。そのため、そのオブジェクトに新しい値を割り当てるのは完全に安全です。

その結果、スワップ機能の初期バージョンは安全です。からデータを移動した後、そのオブジェクトは指定されていない「安全だが予測できない」値を保持します。この値は、移動時に上書きされ、bの値が割り当てられます。

その上に新しいオブジェクトを構築しようとする前に、の存続期間が終了していないため、その2番目のバージョンは安全ではありません。これにより、未定義の動作が発生します。

お役に立てれば!

于 2012-07-27T16:11:12.510 に答える
6

a引き続き有効です。ただし、内部のデータaは信頼できなくなります。リソースを移動するときに割り当てを解除するわけではないaため、新しいリソースをに移動することはまったく問題ありませんa

于 2012-07-27T16:03:43.880 に答える
5

移動してもオブジェクトが無効になることはありません。むしろ、それは一般的に有効であるが不確定な状態のままです。特定のクラスには追加の保証があります。たとえば、std::unique_ptrから移動した後にnullになることを保証します。

有効なオブジェクトが残っているということは、特に、元のコードが行うことである、オブジェクトへの割り当てが完全に問題ないことを意味します。

あなた自身の提案された解決策はひどく壊れています:あなたが古いものの上に新しいオブジェクトを配置-構築するとき、古いオブジェクトの寿命は終わります。ただし、クラスのデストラクタに影響がある場合、デストラクタの呼び出しを省略することは未定義の動作です。

さらに、最初にデストラクタを正しく呼び出した後、コンストラクタで例外が発生した場合、スコープの終了時に破棄する必要のある有効なオブジェクトがないため、問題が発生します。これは、このトピックに関する私の関連する質問です。

于 2012-07-27T16:31:08.580 に答える