非 POD な構造体に fread やら memcpy はしないようにしよう……?

メンバ関数を持った構造体のシリアライズ *1 は有りか無しかと職場で先輩に聞かれたので、とりあえず無理、とだけ答えたのですが、微妙に自信が無くなってきたので調べてみました。

The fread function reads up to count elements from stream into the memory pointed to by ptr. The memory must have POD type (see Chapter 6). Each element is size bytes long. It returns the number of elements that were read successfully.

Roughly speaking, a POD class is a structure that is compatible with C. More precisely, a POD class or union is one that does not have any of the following:


  • user-defined constructors

  • user-defined destructor

  • user-defined copy assignment operator

  • virtual functions

  • base classes

  • private or protected non-static members

  • non-static data members that are references

ということで、ユーザ定義のコンストラクタが存在している時点で POD の条件は満たさず、また非 POD な型の変数を fread に渡すのはよろしくないので NG ということで良いのかな。……と思っていたら、 Web Page Under Construction を見ると書いてあることが違ってちょっと怪しい感じ。

ちなみに実際に試したところ、コンストラクタを定義した構造体を fwrite/fread で読み書きしても普通に動いたとのこと。最初コンストラクタは初回にしか呼ばれないので、その後でいくら fread などで上書きしても問題ないとかとんちんかんなことを考えていましたが、非仮想関数なんだから上書きも何も動いて当然なのですよね。うーん、じゃあ、ありなのか……?

手元の本を漁ってみたところ、 C++ Coding Standard ではやるな、と一言書いてありました。しかし解説には仮想関数があると死ぬということしか書いておらず。それは当然なのですが、仮想関数がない場合はどうなのでしょう。まあでも、 POD 以外はやるな、というのだから、今回の例も無し、ということにしておいてもいいのでしょうか。最初に引用したところにも fread の引数は POD 型を前提としているようなことも書いてありますし。……眠くなってきたので、それでいいか。気が向いたらちゃんと調べます。

こういうことで迷うたびに、基礎が抜けているな、と痛感します。もっと、精進しなくては。

*1:と言っても構造体をバイナリファイルに書いたり読んだりするだけ