このようなコピーコンストラクタの実装にはいくつかの欠点がありますか?
Foo::Foo(const Foo& i_foo)
{
*this = i_foo;
}
私が覚えているように、ある本では代入演算子からコピーコンストラクターを呼び出してよく知られたスワップトリックを使用することが推奨されていましたが、なぜか覚えていません...
このようなコピーコンストラクタの実装にはいくつかの欠点がありますか?
Foo::Foo(const Foo& i_foo)
{
*this = i_foo;
}
私が覚えているように、ある本では代入演算子からコピーコンストラクターを呼び出してよく知られたスワップトリックを使用することが推奨されていましたが、なぜか覚えていません...
はい、それは悪い考えです。ユーザー定義型のすべてのメンバー変数は、最初に初期化され、すぐに上書きされます。
そのスワップトリックはこれです:
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
operator=()
コンストラクターを呼び出すことには、潜在的な欠点と潜在的な利点の両方があります。
コンストラクターは、値を指定するかどうかに関係なく、すべてのメンバー変数operator=
を初期化してから、それらを再度初期化します。これにより、実行が複雑になります。これによりコードに許容できない動作が発生する場合については、賢明な判断を下す必要があります。
コンストラクターとoperator=
緊密に結合されます。オブジェクトをインスタンス化するときに必要なことはすべて、オブジェクトをコピーするときにも実行されます。繰り返しますが、これが問題であるかどうかを賢く判断する必要があります。
あなたはスコットマイヤーズの効果的なC++、アイテム12:「オブジェクトのすべての部分をコピーする」を探しています。その要約は次のように述べています。
- 関数をコピーするには、オブジェクトのすべてのデータメンバーとその基本クラスのすべての部分を必ずコピーする必要があります。
- コピー機能の1つを他の機能の観点から実装しようとしないでください。代わりに、両方が呼び出す3番目の関数に共通の機能を配置します。