スタティック変数とグローバル変数
クラス型のスタティック変数やグローバル変数の使用は禁止する。これらは生成と解放の順序が不定であり、見つけにくいバグを引き起こすためだ。
グローバル変数やスタティック変数、スタティッククラスメンバ変数、関数スタティック変数を含む静的記憶域期間のあるオブジェクトは、POD(Plain Old Data)でなければならない。PODとは、int、char、float、ポインタ、および、PODの配列/構造体のみであることを意味している。
C++では、コンストラクタとスタティック変数のイニシャライザの呼び出し順序が部分的にしか決められておらず、ビルドごとに変わる可能性がある。これにより発見困難なバグが引き起こされる可能性がある。したがって、クラス型のグローバル変数を使うこと、また、関数の結果でスタティックなPOD変数を初期化することを禁止する。ただし、(getenv() や getpid() のように)関数が他のグローバル変数に依存している場合にはその限りではない。
さらに、デストラクタの呼び出し順序はコンストラクタの呼び出し順序の逆順だと定義されている。コンストラクタの呼び出し順序が不定なので、デストラクタの呼び出し順序も不定だということだ。例えば、プログラム終了時にスタティック変数が破壊されても、(おそらく別のスレッドで)まだ動いているコードがその変数にアクセスしようとして失敗するかもしれない。あるいは、スタティックなstring変数のデストラクタが、その文字列への参照を含む別の変数のデストラクタよりも前に呼び出されるおそれもある。
結局のところ、スタティック変数はPODデータを含むときにしか使えないということだ。vector や string も許されない(代わりに、Cの配列や const char* を使うこと)。
もしクラス型のスタティック変数やグローバル変数が必要であれば、main() 関数か pthread_once() 関数で(決して free されることのない)ポインタを初期化することを検討しよう。これはスマートポインタではなく、ただのポインタでなければならないことに注意しよう。スマートポインタのデストラクタにも、これまで回避しようとしてきたデストラクタの呼び出し順序の問題があるためだ。
static クラスメンバ変数はグローバル変数だと見なされることに注意すること。したがって、クラス型にしてはいけない。



