2013/11/04(Mon)C++98 C++03 の POD

はてブ数 2013/11/04 16:21 プログラミング::C++ つーさ

独自コンテナ template struct Container のTがPODだと、
メンバ追加時にコンストラクタもデストラクタも呼ばなくてよい。
コンテナを clear するときも、for (int i = 0; i < size(); i++) this[i]->~T(); する必要が無い。

では、型をPODとして定義するにはどうすればいいのかという話だ。

C++11の情報ばかりヒットして、
C++03までのPODについて、いまいちまとまった情報が得られないので、
自分なりに調べた情報をまとめておく。

C++03までのPOD

PODはaggregateな構造体もしくは共用体。

aggregate

aggregate は 配列、もしくは 次の要件を満たす class である。

  • ユーザ定義のコンストラクタを持たない
  • 基底クラスを持たない
  • static でない private/protected な データメンバ を持たない
  • virtual なメンバ関数を持たない

aggregate ならば、初期化時に SomeClass a = ...; といったように中括弧初期化が行える。
メンバの数が足りなければ、足りない部分は0で埋まる。(0とは0だったり0.0だったりfalseだったりする)
中括弧内の明示的な記述数は0個でもよい(←Cでは違った気がする)。

POD

POD構造体は次の要件を満たすaggregateなstruct。

  • aggregate である。
    • ユーザ定義のコンストラクタを持たない
    • 基底クラスを持たない
    • static でない private/protected な データメンバ を持たない
    • virtual なメンバ関数を持たない
  • ユーザ定義のデストラクタを持たない。
  • ユーザ定義の operator = を持たない。
  • staticでない non-POD型の構造体(とその配列)をメンバを持たない
  • staticでない non-POD型の共用体(とその配列)をメンバに持たない
  • staticでない 参照 を持たない。

POD構造体は次の要件を満たすaggregateなunion。

  • aggregate である。aggregateとはつまり...
    • ユーザ定義のコンストラクタを持たない
    • 基底クラスを持たない
    • static でない private/protected な データメンバ を持たない
    • virtual なメンバ関数を持たない
  • ユーザ定義のデストラクタを持たない。
  • ユーザ定義の operator = を持たない。
  • staticでない non-POD型の構造体(とその配列)を持たない。
  • staticでない non-POD型の共用体(とその配列)を持たない。
  • staticでない 参照を持たない。

補足

C++では、オブジェクトがPODであるときのみ、メモリ上にフィールドが宣言した順番に並ぶことが保証される。
つまり、逆に言えば、コンストラクタ・デストラクタを宣言した時点で、
そのオブジェクトのデータメンバのメモリ上の順番は保証されなくなる。

virtual でないメンバ関数ならば持てる。
operator =以外のoperatorオーバーロードも持てる。
POD型のオブジェクトは、明示的にコンストラクタを呼べば、
データメンバはゼロ初期化される(これはC++03から/Visual Studioなら2005以降)
組み込み型はPODである。

検証コード


ideoneでの実行結果は不定なものゼロになってますが、これはたまたま。

上記コードをVS2013のC++でデバッグビルドすると、

-858993460
0
-842150451
0
-842150451
0
-858993460
0
-858993460
0

が得られます。ここで、
値 -858993460 は 0xCCCCCCCC で stack上の未初期化領域を表し、
値 -842150451 は 0xCDCDCDCD で heap上の未初期化領域を表しています。

C++11では

C++11以降のPODについては色々と制約がゆるくなってるので、また時間があるときにでも書く。
C++11では、コンストラクタを自分で定義しつつ、デフォルトコンストラクタを残すようなことができるので、
各種デフォルトでコンパイラが生成する関数群が(暗黙的・明示的問わず)残されてればよい的な方向にシフトしてる。