コピー コンストラクターと代入演算子を記述する必要があるのは、ポインター データ メンバーがある場合だけですか?
すべてのデータ メンバーがスタックに割り当てられている場合、コンパイラで定義されたコピー コンストラクターと代入演算子に頼ることができますか?
コピー コンストラクターと代入演算子を記述する必要があるのは、ポインター データ メンバーがある場合だけですか?
すべてのデータ メンバーがスタックに割り当てられている場合、コンパイラで定義されたコピー コンストラクターと代入演算子に頼ることができますか?
ポインターは間違いなく最も明白なケースですが、実際には唯一のケースではありません。
もう 1 つの例は、ctor でデータベース接続を開き、dtor で閉じるクラスです。コピー ctor は、データベース接続を複製するために何かを行う必要があるため、データベースへのコピーの接続は、元の接続とは別に閉じられます。
機能する場合は、コンパイラ定義のコピー コンストラクターを使用します。通常、浅いコピーの方が高速ですが、場合によっては、指定されたデータの代わりにポインター アドレスを処理することもあります。たとえば、コードの他の部分と共有するテクスチャへのポインタが必要になる場合があります。
データのコピーが必要な場合にのみ、コピー コンストラクターを修正する必要があります。
警告は、独自のコピー コンストラクターを持つクラスであるメンバー変数であり、何が起こるかについて約束を与えることはできません。
一般的に、私はすべてのリソースをこれらのリソースを維持するクラスに配置するのが好きで、これらのソース メンテナにはコピー コンストラクト、コピー割り当て、およびデストラクタが必要です。リソースによっては、コピーコンストラクタとコピー代入が削除される場合があります。
リソースを直接維持しない一部のクラスではコピー割り当てが必要になる場合があることは明らかではありません。コピー割り当てを強力に例外セーフにしたい場合は、しばしばコピー割り当てを実装する必要があります。たとえば、クラスに 2 つのベクトルが格納されているとします。生成されたコピー割り当ては、メンバーごとの割り当てを行います。通常、メンバーごとの割り当ては問題ありません。ただし、2 番目のベクトルへの代入で例外がスローされると、元の状態に戻すことはできません。より適切なコピー割り当ては次のようになります。
T& T::operator= (T other) {
other. swap(*this);
return *this;
}
swap()
スローせずに実装できるため、この実装は強力な例外セーフです。
基本クラスまたはクラスに含まれるオブジェクトにコピー コンストラクター (つまり、ストリーム) がない場合、クラスをコピー構成可能にしたい場合は、コピー コンストラクターを実装する必要があります。
ストリームの場合、このコピー コンストラクターは、
a) ファイルを複製し、
b) 書き込み可能な新しい空のファイルを作成します。
c) または、ストリームのアドレスを保存して、両方のオブジェクトが書き込みできるようにします。
最後のオプションは最も複雑で、おそらくshared_ptr
.