7

ここでは移動コンストラクタで、ほとんどの任意のクラスのための移動の割り当てを定義するための非常に簡単な方法です:destruct + move構造による移動代入は安全ですか?

class Foo { 
public: 
    Foo(Foo&& foo);      // you still have to write this one 
    Foo& operator=(Foo&& foo) { 
    if (this != &foo) {    // avoid destructing the only copy 
     this->~Foo();     // call your own destructor 
     new (this) Foo(std::move(foo)); // call move constructor via placement new 
    } 
    return *this; 
    } 
    // ... 
}; 

は、標準C++ 11でこのポインタ安全上の新しい配置に続いて、独自のデストラクタを呼び出して、この一連のです?

+2

あなたの移動コンストラクタは 'noexcept'である方が良いでしょう。もしUB土地でスローされてさまよっていれば、既に破壊されたオブジェクトを破壊しようとします。 – ildjarn

+1

移動/コピー割り当てのための良いトリックは単純に[値によ​​ってパラメータを取る]ことです(http://stackoverflow.com/questions/9746748/does-it-make-sense-to-reuse-destructor-logic-by- using-stdswap-in-a-move-assign/9746772#9746772)。ユーザーは、値のパラメータを移動または構成するか(またはその中に入る)かのどちらかを行います。次に、 'std :: swap'を使って値をあなたのオブジェクトに入れ替えることができます。 –

答えて

6

あなたがこのクラスから型を派生したことがない場合に限り、そうすると、オブジェクトが怪物に変わります。標準では、これをオブジェクトの存続期間の説明の例として使用することは残念です。実際のコードで行うのは本当に悪いことです。

+0

新たに割り当てられたメモリを手動で取得してから配置し直しても問題はありますか?私はこれが自分自身が許可されていることを確認するために標準的に掘り下げなければならないでしょう。 – Yakk

+0

@Yakk no、あなたは何も割り当てていないからです。 –

+0

@ Yakkいいえ、最初に割り当てたオブジェクトが、配置newを使って作成するオブジェクトに十分なサイズと位置合わせの要件を満たし、削除するために渡すポインタが適切なタイプである限り、その点で問題はありません。 – bames53

0

技術的には、この小さな例では、ソースコードは安全なです。しかし、現実はあなたがFooを面白く見ることさえすれば、あなたはUBを呼び出すでしょう。それは完全に価値がないので、非常に臆病に危険です。みんなのようにスワップを使ってください。それは理由があります。それは正しい選択だからです。また、自己割り当てチェックが悪いです。

+2

コピーとスワップは常に最適な実装ではありません。それは強力な例外安全の保証を得る簡単な方法ですが、トレードオフがあります。 Howard Hinnantは、[this](http://stackoverflow.com/a/6687520/365496)の答えの一部についていくつか説明しています。 – bames53

+0

あなたの懸念は主に派生クラスの作成者(誤ってこの場合)Fooの移動割り当てを呼び出すか、それ以上の問題がありますか?この手法では、サブクラスの作成者は事実上オーバーライドしてこの手法を使用する必要があります。私が考えることができる問題の多くは、移動割り当てが仮想ではなく、答えがちょうど、この技法が使用されているかどうかにかかわらず、移動割り当てがそれらの場合に仮想でなければならないということです。それ以上の懸念はありますか? –

関連する問題