DOSEIの日記

技術メモ+日常ログ

value-initialized array by new operator

規格では 5.3.4 の 5 で、

int * a = new int [100] ();

のように最後に括弧をつけることによって、 int 等の型でも value-initialized されることが規定されている。しかし、なぜか配列の new は初期化できないという説明がちまたであふれかえっている。どうも、過去のコンパイラによるバグ実装がいけないらしい。 実際、 gcc でちゃんとゼロ初期化されないバージョンがあったらしい。最近のはちゃんとできるはず。以下の記事参照。

で、

#include <cstdlib>
#include <iostream>
int main()
{
  double *a;
  a = new double[10000];
  a[8]=1000;
  delete[] a;

  double *b = new double[10000]();
  //double *b = new double[10000];  // こっちだと abort する。
  //double *b = new double[10000](3.14);  // *2: 規格上はできそうなんだけどなぁ

  if(a!=b) // *1
  {
    std::cerr << "! not same address\n";
    abort();
  }

  for(int i=0; i<10000; ++i)
    if (b[i] != 0) { std::cerr << i << "\n";  abort(); }
}

こんなコードで確認した。最初に確保した領域に値を書き込んで、解放したうえでもう一度確保する。普通は同じ場所に確保されるので、それを確認してから (*1) ループでゼロクリアされたかチェック。括弧なしだとアボートして、カッコありだとすべて 0 になっていることがわかる。


ところで、 (*2) のように書けるかどうかだが、規格の同じ場所には、カッコの中にただ一つの値が書かれている場合は、その値で初期化できる、と書かれているように読めるのだが、 gcc
エラー: ISO C++ forbids initialization in array new [-fpermissive] となってコンパイルできない。 -fpermissive をつけても、エラーが警告に代わるだけで、初期化が行われるわけではない。

だれかどっちが正しいのか教えてください…。

Egtra さんからのコメントによる追記。どうやら C++11 の規格ではここの表現かわかって、できない感じになっているらしい。しかし、あくまでも C++03 ならできるんじゃないかと思うんだけどなぁ。できないんだとしたら、 5.3.4-15 の文は意味がない気がする。