constポインタとC++の必勝形

先週作成したプログラムの点検をしているときに、一つ発見があった。

あるオブジェクトが、ポインタ型の変数をメンバ変数としてもつ場合を考える。ポインタ領域が解放された後に、その変数へのアクセスが行われると致命的なエラーとなる。したがって、ポインタの生存期間は、オブジェクトの生存期間よりも長くなければいけない。僕は、9/23の日記で、ポインタの生存期間の問題は、設計時に良く考えなければいけない問題だと述べた。しかし、そのような良く練られた設計を、プログラムの中で表現する方法については何も述べていなかった。

その一つの答え。ポインタ型のメンバ変数を、すべてconstにする。

ポインタをconstにすると、オブジェクトのコンストラクタ時に、ポインタはセットされなければならない。それには以下の二つのケースがある。

  • コンストラクタ時に新たに領域が確保される場合。この場合は、デストラクタ時に領域を解放すれば良い。これで、オブジェクト生存中に、ポインタが解放されないことが保障される。
  • コンストラクタの引数でポインタが渡される場合。通常のプログラミングスタイルに従う場合、オブジェクトの生成とオブジェクトの解放は対で行われる。すなわち、この場合は、そのコンストラクタが呼び出されるスコープ内でデストラクタも呼び出されるはずだ。この場合、そのコンストラクタにオブジェクトよりも生存期間が短いポインタを渡していないことを容易に確認できる。

僕は、Javaプログラミングのときから、「オブジェクトはすべてfinal」というルールに従ってプログラミングしていた。したがって、その良さ(ヌルポインタへのアクセスを根絶できること)は十分知っているつもりだった。しかし、C++にそのルールを適用してみると、新しい世界が開けたように思う。

ガベージコレクションではなく、もっとシンプルなメモリ解放セマンティクス(スコープを外れたときにメモリ領域が解放される)をもつプログラム。同時に、解放されたメモリへのアクセスが起こりようがない形で組み立てられているプログラム。僕がずっと探している「C++の必勝形」とは、こういうものだったんだな。