[迷信] コンストラクタで自身をゼロクリア

世の中には怖いもの知らずというか、とんでもないコードを書く人たちがいます。例えば、

struct foo
{
  std::string str;
  int a;
  int b;
 
  foo()
  {
    std::memset(this, 0, sizeof(*this));
  }
};

のようなコードです。さすがにこれはクラッシュする可能性が高いので、実行させてみれば間違いに気付くことでしょう。しかし、こんなのはどうでしょうか?

struct bar
{
  std::pair<long, double> x;
  int a;
  int b;
 
  bar()
  {
    std::memset(this, 0, sizeof(*this));
  }
};

これだと動いてしまう処理系のほうが多そうです。std::pair のようなクラスを std::memset でゼロクリアするのはもちろん反則ですので、未定義の動作になるわけですが、たまたま動いてしまうわけです。

では、std::string や std::pair のようなクラスを一切メンバに持たない、すなわちC互換型だけをメンバに持つような構造体であれば、コンストラクタでこのようなゼロクリアを行ってもよいのでしょうか?

そんなはずはありませんね。明示的なコンストラクタを定義した時点で、その構造体はもはやC互換構造体ではなくなります。C互換型ではないオブジェクトを std::memset でクリアすることはできません。多くの場合は動くかもしれませんが、それはあくまでもたまたまです。メンバの構成が変更されれば実害が出ることも十分考えられるので、こんなコードを書くのは避けるべきです。

この記事のトラックバックURL:

http://www.kijineko.co.jp/trackback/588