web-dev-qa-db-ja.com

コピーコンストラクターで代入演算子を呼び出す

コピーコンストラクタのそのような実装のいくつかの欠点はありますか?

Foo::Foo(const Foo& i_foo)
{
   *this = i_foo;
}

私が覚えているように、ある本では、代入演算子からコピーコンストラクターを呼び出して、よく知られたスワップトリックを使用することが推奨されていましたが、覚えていません、なぜ...

29
stas

はい、それは悪い考えです。ユーザー定義タイプのすべてのメンバー変数は、最初に初期化され、次にすぐに上書きされます。

そのスワップトリックはこれです:

Foo& operator=(Foo rhs) // note the copying
{
   rhs.swap(*this); //swap our internals with the copy of rhs
   return *this;
} // rhs, now containing our old internals, will be deleted 
20
sbi

コンストラクターでoperator=()を呼び出すことには、潜在的な欠点と潜在的な利点の両方があります。

欠点:

  • コンストラクターは、値を指定するかどうかに関係なく、すべてのメンバー変数を初期化し、次にoperator=はそれらを再度初期化します。これにより、実行が複雑になります。これによりコードに許容できない動作が発生する場合については、賢明な判断を下す必要があります。

  • コンストラクターとoperator=緊密に結合されます。オブジェクトをインスタンス化するときに必要なことはすべて、オブジェクトをコピーするときにも実行されます。繰り返しますが、これが問題であるかどうかを賢く判断する必要があります。

利益:

  • コードベースの複雑さが軽減され、保守が容易になります。繰り返しになりますが、このゲインの評価については賢明です。 2つの文字列メンバーを持つ構造体がある場合、それはおそらく価値がありません。一方、50人のデータメンバーがいるクラス(おそらくそうすべきではありませんが、それは別の投稿の話です)または互いに複雑な関係を持つデータメンバーがある場合は、1つだけにすることで多くのメリットがあります2つ以上の代わりにinit関数。
8
John Dibling

探しているのは ScottMeyersのEffectiveC++ アイテム12:オブジェクトのすべての部分をコピーします。

3
Billy ONeal