Arantium Maestum

プログラミング、囲碁、読書の話題

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される(ちゃんとデストラクタが設計されていれば))