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 の文は意味がない気がする。