2011-08-24 4 views
6

背景: 私は多くの変数を持つ複雑なクラスを持っています。オペレータ=のプレースメントnew(this)を使用できますか?

インテリアライザリストで呼び出されたメンバー変数コピーコンストラクタの中には、割り当てを実行するものがあります。

質問: operator=を作成する必要があります。むしろ代わりに初期化リストの割り当てで既存のconstuctorを複製し、交換されるのメモリを解放し、などなどなどよりも、私は単純に次の操作を実行できます。つまり

Applepie& Applepie::operator=(const Applepie &copy) 
{ 
    if(this != &copy) 
    { 
     this->~Applepie(); // release own object 
     new(this) Applepie(copy); // placement new copy constructor 
    } 
    return *this; 
} 

、配置に続いて自己を破壊していますオペレータと意味的に同じ新しいコピーコンストラクタ=

これは劇的に繰り返しコードを削減し、各変数は代入時の効率の潜在的なわずかな損失のコストで、正しく初期化されていることを確認する可能性を持っているようです。私は何かをもっと不明瞭にしていますか?

理由: 私の実際のクラスには約30の偽りがあります。私は、コピーコンストラクタと代入オペレータの両方が30個すべてをコピーしなければならず、コードが分岐して2つの操作が異なる方法で動作することが懸念されます。 「例外C++」の状態でハーブサッターよう

+4

コピーctorのがスローした場合は、オブジェクトが壊れているので、あなたはどのexpection安全保証を与えていません。 –

+1

@R Martinho - 私は手動で各変数を割り当てていたとしても、コピー元がスローすると、私の演算子=スローされてしまうようです。 – jcwenger

+3

問題は 'operator =' throwingではなく、 'operator ='はオブジェクトを無効な状態にしています!それは破壊されている。 –

答えて

6

、それは例外安全ではありません。つまり、newの間に何かが間違っていたり、新しいオブジェクトが作成されたりすると、割り当ての左手オペランドが悪い(定義されていない)状態になり、さらに問題が発生します。 copy & swap idiomを使用することを強くお勧めします。

Applepie& Applepie::operator=(Applepie copy) 
{ 
    swap(m_crust, copy.m_crust); 
    swap(m_filling, copy.m_filling); 
    return *this; 
} 

あなたのオブジェクトがPIMPLイディオム(実装へのポインタ)を使用する場合も、スワップが2つだけのポインタを変更することで行われます。ルネの答えに加えて

+1

+1 'swap'は素晴らしい過小評価されています関数...追加の利点:引数がrvalueの場合、コンパイラはコピーelisionを実行できます。 –

+0

だから私の実際のクラスには約30の変数があります。私のコピーコンストラクタはイニシャライザリストに30個の変数を持っています。コピー&スワップにはまだ30のスワップ()コールが必要です - 私の目的はApplepieのパイ(オリジナル)の可能性を減らすことです。アップルパイリンゴ。リンゴ=オリジナル;異なる結果を生み出す。 – jcwenger

+0

@ jcwenger:はい、それはトラブルの呼び出しです。したがって、* Pimpl *イディオムの候補者かもしれませんが、それに切り替える前に、コストがかかっていると考えてください。各メンバーのアクセスは、ポインタを通過しています。もう一つのアイデアは、あなたの 'Applepie'クラスを小さなものに分割することです。あるクラスに30人のデータメンバーがいる場合、デザインに何か問題があるかもしれません... –

0

は、ApplePieは、実際のオブジェクトの基本クラスだった場合に何が起こるかの問題もある。ApplePieは、間違った型のオブジェクトを持つオブジェクトを交換することになります!

+1

オブジェクトがHandle-Workerイディオムで実装されていない場合、演算子=はオブジェクトのスライス*を行います。 –

関連する問題