g++でコンパイルが非常に遅くなる短い例

次の短いC++プログラムをg++ -g -O1などでコンパイルしてみると、非常に時間がかかります。最適化レベルは、-O0以外のどの最適化でも発生します。

struct Int {
    int n;
    Int() : n(0) {}
};

struct Array {
    Int data[8000];
    Array() : data{} {}
} arr;

[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ

特にテンプレートを使っているわけでもないのに、なぜこんなに遅くなるのでしょうか。

これは、Intのユーザー定義コンストラクタがインライン展開され、それぞれにデバッグ情報をつけて回っているのが原因のようです。実際、-cオプションでオブジェクトファイルを生成し、objdumpコマンドで中身を確認してみると、大量のデバッグ情報が埋め込まれていることが分かります。

この問題を防ぐには、以下のいずれかを実行すればよいです。

  1. 最適化を掛けないでコンパイルする
  2. -gをつけないでコンパイルする
  3. g++ではなくclang++を使ってコンパイルする
  4. 生配列を用いる(明示的に初期化してもこの問題は発生しない)
  5. Arrayのコンストラクタで明示的に初期化しないでデフォルト初期化に任せる(std::arrayはそうなっている。ただし、intのような非クラス型のデフォルト初期化は「未初期化」なので注意しなければいけない)
  6. 呼び出されるIntのコンストラクタをデフォルトコンストラクタにする(nを初期化するとき、ユーザー定義コンストラクタではなくデフォルトメンバ初期化を使う)

この中では、最後の手法がおすすめです。特に、Arrayをテンプレート化し、intのような非クラス型を受け取ったとしても未初期化にならないようにしたい、という場合はこの方法を使うしかなさそうです。