std :: arrayのデフォルトの初期化?


103

C ++ 11 std::arrayでは、構文std::array<T, N> x;が配列のすべての要素をデフォルトで初期化することが保証されますか?

編集:そうでない場合、すべての要素をデフォルト値に初期化するためにすべての配列(サイズがゼロの配列を含む)で機能する構文はありますか?

編集cppreferenceで、デフォルトのコンストラクタの説明は次のように述べています:

(constructor) (implicitly declared) (public member function)
default-constructs or copy-constructs every element of the array 

そう答えはイエスかもしれません。しかし、私はそれを標準または将来の標準に従って確認したいと思います。


そう思わないでください。デフォルトで宣言されているため、基本的にはT x[N]構文と同等です。
Rapptz 2013

回答:


148

定義により、デフォルトの初期化は、他の初期化が指定されていないときに発生する初期化です。C ++言語では、明示的な初期化子を指定しないオブジェクトはすべてデフォルトで初期化されます(C ++ 11§8.5/ 11)。タイプstd::array<T, N>とのオブジェクトが含まれますT[N]

デフォルトの初期化が効果を持たず、オブジェクトの値を不確定のままにするタイプがあることに注意してください:非クラス、非配列タイプ(8.5 / 6)。その結果、そのようなタイプのオブジェクトのデフォルトで初期化された配列は、不確定な値を持ちます。例:

int plain_int;
int c_style_array[13];
std::array<int, 13> cxx_style_array;

Cスタイルの配列も、std::array不確定値の整数と同様に、不確定値の整数で埋められplain_intます。

すべての要素をデフォルト値に初期化するために、すべての配列(サイズがゼロの配列を含む)で機能する構文はありますか?

「デフォルト値に」と言うとき、あなたは本当に「すべての要素を初期化する」ことを意味していると思いますT{}。これはdefault-initializationではなく、value-initialization(8.5 / 7)です。C ++ 11では、各宣言に空の初期化子を与えることで、値の初期化を非常に簡単に要求できます。

int plain_int{};
int c_style_array[13]{};
std::array<int, 13> cxx_style_array{};

これにより、すべての配列要素が順番に値初期化されplain_old_int、と、両方の種類の配列のすべてのメンバーがゼロに初期化されます。


クラスメンバーの場合はどうでしょうか。struct X {std :: array <int、12> dozen; X():dozen(){} 12個のゼロが得られますか?
gerardw 2013年

4
@gerardw標準によると、そうです。MSVCのバグに注意してください。値の初期化のいくつかのケースを正しく実装できません。
ケーシー

1
実際、boostはそう言っており、boost::value_initialized リンクで回避しますが、VC12(VS2013)の方がはるかに優れたサポートを提供していると思います。
v.oddou

1
コミティが標準をデフォルト値の初期化に変更し、要求に応じて値を損なったことを願っています。すなわちstd :: array <int、12> = {std :: undetermined}; または何か
Viktor Sehr

実際には、何かを不確定な値に初期化することはどういう意味ですか?代替は何ですか?
Andrew

21

デフォルトの初期化は、標準からの用語であり、初期化をまったく行わない可能性があるため、おそらくゼロ初期化を意味します

cppreference.comの説明は、実際には少し誤解を招くものです。std::arrayは集約クラスであり、要素タイプがプリミティブである場合、それはPOD:「プレーンな古いデータ」であり、セマンティクスはC言語に厳密に一致しています。の暗黙的に定義されたコンストラクタstd::array< int, N >は、まったく何もしない簡単なものです。

ゼロ化された値を提供するstd::array< int, 3 >()またはのような構文はstd::array< int, 3 > x{}、コンストラクターを呼び出すことによってそうしません。ゼロの取得は、C ++ 11§8.5/ 8で指定されているvalue-initializationの一部です。

タイプTのオブジェクトを値初期化するとは、次のことを意味します。

— Tが(おそらくcv修飾された)クラス型であり、ユーザーが提供または削除したデフォルトコンストラクターがない場合、オブジェクトはゼロで初期化されます。Tが自明でないデフォルトコンストラクターである場合、オブジェクトはデフォルトで初期化されます。

std::arrayユーザー指定のデフォルトコンストラクターがないため、ゼロで初期化されます。暗黙的に定義されたデフォルトのコンストラクタがありますが、それは取るに足らないことなので、デフォルトで初期化されることはありません。(しかし、定義による些細な初期化は実行時に効果がないので、これは違いを作りません。)

そうでない場合、すべての要素をデフォルト値に初期化するために、すべての配列(サイズがゼロの配列を含む)で機能する構文はありますか?

Cスタイルの配列とstd::arrayはどちらも集約であり、集約を完全にゼロ初期化する方法は構文を使用すること= {}です。これはC ++ 98以降で機能します。Cスタイルの配列はエクステントをゼロにすることはできず、ゼロではないことに注意してくださいsizeof (std::array< X, 0 >)


6

両方とも、配列のすべての要素をデフォルトで初期化T x[N];std::array<T, N> x;ます。

たとえば、の場合T = std::string、すべての要素は空の文字列になります。Tがデフォルトのコンストラクターのないクラスの場合、どちらもコンパイルに失敗します。の場合T = int、すべての要素の値は不確定になります(宣言がたまたま名前空間スコープにある場合を除く)


0

まず、T x [N]はデフォルトで要素を初期化しますが、スカラー型Tのデフォルトの初期化は実際には何もしません。上記はstd :: array xにも当てはまります。必要なのはリストの初期化だと思います。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.