11

背景: 私は多くの変数を持つ複雑なクラスを持っています。私は健全でテスト済みのコピーコンストラクターを持っています:

Applepie::Applepie( const Applepie &copy) :
m_crust(copy.m_crust),
m_filling(copy.m_filling)
{
}

初期化リストで呼び出されるメンバー変数コピーコンストラクターの一部は、割り当てを実行します。

質問: を作成する必要がありますoperator=。初期化リストの代わりに代入を使用して既存のコンストラクターを複製したり、置き換えられるメモリを解放したりするのではなく、次のようにすることができます。

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

言い換えると、destroy selfの後に、operator =と意味的に同一の配置新しいコピーコンストラクターが続きますか?

これにより、繰り返しコードが大幅に削減され、各変数が適切に初期化されていることを確認できる可能性がありますが、割り当て中に効率がわずかに低下する可能性があります。もっとあいまいなものが欠けていますか?

理論的根拠: 私の実際のクラスには約30の変数があります。コピーコンストラクターと代入演算子の両方が30個すべてをコピーする必要があり、コードが分岐して2つの操作の動作が異なる可能性があるという事実を懸念しています。

4

2 に答える 2

6

「例外的なC++」のハーブサッターが述べているように、それは例外安全ではありません。つまりnew、新しいオブジェクトの作成中または作成中に問題が発生した場合、割り当ての左側のオペランドが不良(未定義)状態になり、さらに問題が発生します。コピー&スワップイディオムを使用することを強くお勧めします。

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

オブジェクトがPimplイディオム(実装へのポインター)も使用している場合、スワップは2つのポインターのみを変更することによって行われます。

于 2011-08-24T15:23:20.710 に答える
1

Reneの答えに加えて、ApplePieが実際のオブジェクトの基本クラスである場合にどうなるかという問題もあります。ApplePieはオブジェクトを間違ったタイプのオブジェクトに置き換えます。

于 2011-08-24T15:31:39.223 に答える