C ++でコピーコンストラクターと代入演算子を記述するためのチェックリスト
-
03-07-2019 - |
質問
例外の安全性の維持、メモリリークの回避などのために、コピーコンストラクタと割り当て演算子がC ++で実行する必要があるタスクのリストを作成してください。
解決
まず、コピーを本当にサポートする必要があることを確認してください。ほとんどの場合そうではないので、両方を無効にするのが良いでしょう。
場合によっては、ポリモーフィックな階層からクラスを複製する必要があります。その場合は、割り当て演算子を無効にし、(保護された?)コピーコンストラクタを記述し、仮想clone()関数を提供します。
それ以外の場合、値クラスを記述している場合、Coplienの直交正準形の土地に戻ります。簡単にコピーできないメンバーがいる場合は、コピーコンストラクター、デストラクター、代入演算子、およびデフォルトコンストラクターを提供する必要があります。このルールは改良できます。たとえば、ビッグツーの法則
割り当て演算子に関するC ++ FAQも参照することをお勧めします。 、および copy-and-swapイディオムおよび GOTW で。
他のヒント
コンパイラ生成バージョンは、ほとんどの状況で機能します。
オブジェクトにRAWポインター(RAWポインターを持たないための引数)が含まれている場合、問題について少し難しく考える必要があります。 RAWポインターがあります。2番目の質問は、ポインターを所有していますか(削除されていますか)。その場合、4のルールを適用する必要があります。
1つ以上のRAWポインターを正しく実行することはますます難しくなります(複雑さの増加も直線的ではありません[ただし、これは観察的であり、そのステートメントをバックアップする実際の統計はありません)。したがって、複数のRAWポインターがある場合は、それぞれを独自のクラス(何らかの形のスマートポインター)でラップすることを検討してください。
4のルール:オブジェクトがRAWポインターの所有者である場合、次の4つのメンバーを定義して、メモリ管理を正しく処理することを確認する必要があります。
- コンストラクター
- コンストラクタのコピー
- 割り当て演算子
- デストラクタ
これらの定義方法は状況によって異なります。ただし、次の点に注意してください:
- デフォルトの構築:ポインターをNULLに設定
- コピーコンストラクター:コピーとスワップのアイデアを使用して、「強い例外保証」に提供します
- 割り当て演算子:自分への割り当てを確認する
- デストラクタ:デストラクタから伝播する例外から保護します。
これを読んでみてください。
http://www.icu-project.org/docs /papers/cpp_report/the_anatomy_of_the_assignment_operator.html
代入演算子の非常に優れた分析
ここでは安全に例外についての見当がつかないが、私はこのようにしている。テンプレート化された配列ラッパーであると想像してみましょう。役に立てば幸いです:)
Array(const Array& rhs)
{
mData = NULL;
mSize = rhs.size();
*this = rhs;
}
Array& operator=(const Array& rhs)
{
if(this == &rhs)
{
return *this;
}
int len = rhs.size();
delete[] mData;
mData = new T[len];
for(int i = 0; i < len; ++i)
{
mData[i] = rhs[i];
}
mSize = len;
return *this;
}