Effective C++勉強メモ: Item 11 自己への代入に気をつけよう
例えばBオブジェクトがprivateデータメンバとしてAオブジェクトへのポインタを保持しているとする:
class A {}; class B { private: A* pa; public: B& operator=(const B& rhs) { delete pa; pa = new A(*rhs.pa); return *this; } };
上記のようなoperator=
だと
a = a
のような自己代入が起きた時new A
が例外を投げた時
に、すでにdeleteしたポインタをオブジェクトが持ち続けてしまい、バグの温床になる。
B& operator=(const B& rhs) { if (this == &rhs): return *this delete pa; pa = new A(*rhs.pa); return *this; }
のようにoperator=の冒頭で自己同一性を確認するスタイルも非常によく見られるが、後者の問題(Exception Unsafe)への対処にはならない。
B& operator=(const B& rhs) { A* pOld = pa; a = new A(*rhs.pa); delete pOld; return *this; }
のように古いポインタをdeleteするのを関数の最後に持ってくるか
B& operator=(const B& rhs) { B temp(rhs); swap(temp); return *this; }
copy & swapイディオムを使ってそもそもdeleteをしないか、が推奨。(swap元のrhsオブジェクトのデストラクタが呼ばれる時に、そこでdeleteされる(ちゃんとデストラクタが設計されていれば))