3

コピー コンストラクターとオーバーロードされた = 演算子を適切に実装した C++ クラスがあるとします。適切に実装されているということは、それらが機能しており、ディープコピーを実行していることを意味します。

Class1::Class1(const Class1 &class1)
{
  // Perform copy
}
Class1& Class1::operator=(const Class1 *class1)
{
  // perform copy
  return *this;
}

今、私もこのコンストラクターを持っているとしましょう:

Class1::Class1(Class1 *class1)
{
   *this = *class1;
}

私の質問は、上記のコンストラクターは許容される方法でしょうか? これは、私が継承して維持しているコードです。

4

4 に答える 4

7

以下の理由から、私は「いいえ」と答えます。

  • 従来のコピー コンストラクターは、その引数をポインターとしてではなく、const 参照として受け入れます。
  • ポインターをパラメーターとして受け入れる場合でもconst Class1*、引数が変更されないことを示す必要があります。
  • のすべてのメンバーClass1がデフォルトで初期化されてから、operator=
  • operator=同じ問題があります。ポインターではなく参照を受け入れる必要があります。

コピー コンストラクターを「再利用」する従来の方法operator=は、コピー アンド スワップ イディオムです。そのようにクラスを実装することをお勧めします。

于 2010-04-30T16:45:36.007 に答える
2

これまでに説明したことよりも重要な問題は、非標準代入演算子がコンパイラによる標準代入演算子の生成を停止しないということです。代入演算子を作成する必要があると判断したため (コピー コンストラクターを作成したため、当然のことです)、既定値では十分ではありません。したがって、このクラスのユーザーは、ほとんどの人にとって非常に基本的で標準的なオブジェクトの使用中に、この問題の餌食になる可能性があります。

于 2010-04-30T16:57:20.553 に答える
2

個人的には、それは良い習慣ではないと思います。

コンストラクターにとって、オブジェクトへのポインターからオブジェクト自体への暗黙的な変換が役立つ場所を考えるのは困難です。

ポインターが非 const になる理由はありません。また、クラスへの使用可能なポインターがあれば、それを逆参照することは難しくないため、コピー コンストラクターを使用してオブジェクトをコピーする意図を明確に示します。

同様に、非標準の代入演算子の場合、呼び出しサイトで正しく逆参照する方が明確で慣用的であるのに、ポインターからの代入を許可するのはなぜですか?

于 2010-04-30T16:43:52.997 に答える
1

オブジェクトとオブジェクトへのポインターは、2 つのまったく異なるものです。通常、オブジェクトを渡すときは、それらがコピーされることを期待します (ただし、理想的には、不要なコピーを削減/排除するために、可能な場合は関数が const ref を使用します)。ポインターを渡しているとき、コピーが行われることは期待していません。特定のオブジェクトへのポインターを渡していますが、コードによっては、その特定のオブジェクトのコピーではなく、その特定のオブジェクトを処理することが重要になる場合があります。

型へのポインターを受け取る代入演算子とコンストラクター (特に暗黙的な変換に使用できるコンストラクター) は、実際に物事を混乱させ、意図しないコピーを作成する可能性が高くなります。これは、パフォーマンスの問題になるだけでなく、バグ。

型へのポインターと型自体との間の変換を暗黙的に、または明示的にしたいという正当な理由は考えられません。これを行う組み込みの方法は、オブジェクトを逆参照することです。この種のことが必要な場合や良い考えであるとは考えられない特定の状況がいくつかあるのではないかと思いますが、それは本当に疑わしいです。確かに、そうする具体的かつ正当な理由がない限り、そうしないことを強くお勧めします.

于 2010-04-30T16:53:45.703 に答える