2016-09-10 25 views
4

structの省略形の定義で、問題点のみを示しています。構造体宣言で空のカッコはどういう意味ですか?

struct Entry { 
    // bookkeeping record for managing solution search 
    std::array<std::array<bool, DIM>, DIM> filled; // which holes have been filled 
    std::array<std::array<char, MAX>, MAX> cells; // individual cell entries, 0=empty 
    std::vector<Constraint> overlaps; 
    std::vector<Hole*>::iterator candidates; 
    Entry() = default; 
}; 

これは実際には間違いでした。私は、デフォルトのコンストラクタが配列を0で初期化すると思っていましたが、ランダムなガベージでそれらを埋めています。私は今、デフォルトのコンストラクタを書く必要があることを知っていますが、私はテスト時に遭遇した動作に混乱しています。

は、これは私のテスト関数のカットダウン版です:私はこれを実行したとき

void testEntry(void) { 
    Entry e; 
    std::cout << std::boolalpha; 
    e.cells[1][2] = 'a'; 
    e.filled[0][0] = true; 
    for (int i = 0; i < MAX; ++i) 
     for (int j = 0; j < MAX; ++j) 
      std::cout<<i<<" "<<j<<" "<<e.cells[i][j]<<std::endl; 
    for (int i = 0; i < DIM; ++i) 
     for (int j = 0; j < DIM; ++j) 
      std::cout<<i<<" "<<j<<" "<<e.filled[i][j]<<std::endl; 
} 

filledcells配列はランダムなゴミを含有し、最終的に私は私のミスを発見しました。デバッグ中に、Entry e;という宣言をEntry e{};に変更し、変更されたコードが意図したとおりに動作するように見えますが、理由はわかりません。

私はその文書に従うことができません。 list initializationの下では、 "braced-init-listが空で、Tがデフォルトのコンストラクタを持つクラス型である場合、値の初期化が実行されます。"これはかなり明確ですが、私がvalue initializationに行くと、ケースのどれが適用されるのか分かりません。 zero-intializationの下のこの句のように思われる "Tが非共用体のクラス型である場合、すべての基本クラスと非静的データメンバーはゼロで初期化され、すべての埋め込みはゼロビットに初期化されます。いずれも無視されますが、私はここに来る方法は分かりません。

何よりも、この動作が実際に仕様で定義されているのか、それとも別のコンパイラで異なるのか疑問です。 (私はXcode 7.2.1の下でclangを使用しています)。

+2

"Tが、ユーザ提供も削除もされないデフォルトのコンストラクタを持つクラス型である場合(つまり、暗黙的に定義されたデフォルトコンストラクタを持つクラスである場合)、オブジェクトはゼロで初期化され、 " – cpplearner

+0

あなたはこの質問にC++ 11というタグを付けましたが、C++ 11やC++ 14に興味があるだけですか?私が間違っていなければ、C++ 14はこの集計の初期化を行います。 – hvd

+1

'[...]' ==かっこ、 '(...)' ==かっこ、 '{...}' ==中かっこ。あなたのコードは3つすべてを持っていて、あなたはタイトルの中だけに「大括弧」と書いてあります。質問が何であるかを理解するために不必要に難しい作業をしなければなりません。デフォルトのコンストラクタは配列に「ランダムなジャンク」を埋め込むわけではありません。まったく何もしません。ランダムなジャンクは、使用されたメモリの中にあったものです。 – Clifford

答えて

6

構造体宣言で空白の括弧は何を意味しますか?

T object {};value initialization (4)の構文です。中かっこなしでは、オブジェクトはdefault initializedになります。

ペダンティックであるために、これは「構造体宣言」ではありません。これは変数の宣言です。

私が値の初期化に行くとき、どのケースが該当するかはわかりません。

この1が適用されます。

2)Tは、いずれもユーザ提供も削除(つまり、デフォルトのコンストラクタを持つクラス型である場合、それは暗黙的に定義を持つクラスであってもよいですまたは既定の既定のコンストラクターがある場合)、オブジェクトはゼロで初期化され、デフォルトで初期化されます。 (C++ 11以降)

これは初期化をゼロにする方法です。ゼロ初期化ルールの解釈は正しいです。

この動作は実際にリンクされたページで

ルールが標準ではなく、特定の実装に基づいている仕様で定義されている場合、私は思ったんだけど。動作が定義されています。

+0

ありがとうございます。 「デフォルトのデフォルトコンストラクタ」というフレーズは私が見落としたものです。 – saulspatz

1

標準の用語はC++ 11とC++ 14の間で変更され、最終結果は似ていますが同一ではありません。初期化され(空いえ)ブレースリストため


このコードは、リスト初期化あります。 C++ 11 [dcl.init.list]/3から以下の引用が適用されます。

次のようにT型のオブジェクトまたは参照のリスト初期化が定義されている:

  • 場合初期化子リストに要素がなく、Tがデフォルトのコンストラクタを持つクラス型である場合、オブジェクトは値で初期化されます。次のようにオブジェクトまたは型Tの参照の

    リストの初期化が定義されている:C++ 14と同じセクション内しかし

は異なる箇条書き始まる

  • Tが集約である場合、集約初期化が実行されます。
この場合

、それが1([dcl.init.aggr]/1)の条件を満たしているので、Entryの集合体である:

凝集体のないユーザ提供コンストラクタ(持つ配列またはクラスであります

「ユーザー提供」という用語は、既定の機能を除外しています。

集約初期化の動作は[dcl.init.aggr]で説明されています。これは、リストの連続するメンバーが集約のメンバーの初期化子とみなされることを示します。凝集体より少ないリストのメンバーが存在する場合、次に[dcl.init.aggr]/7が適用されます。

少ない初期条項がリストにある場合はメンバーが合計であるよりも、各メンバではありません明示的に初期化されたものは、中括弧または同等の初期化子から初期化するか、またはブレースまたは同等の 初期化子がない場合は、空の初期化子リストから初期化します。

これは、例えば、e.overlapsstd::vector<Constraint> overlaps{};のようになりますと同じように初期化されている、と言っています。

これは集計の再帰的定義であることに注意してください。集計ではないもの(たとえばstd::vector)に到達すると、[dcl.init.list]/3の2番目の箇条書きが適用されます。これはC++ 11の最初の値:value-initializationです。 C++ 14とC++ 11を比較


は、小さな差が存在する:C++ 14にメンバのデフォルトコンストラクタを呼び出す前にゼロ初期化オブジェクト全体段差が存在しません。代わりに、ユーザが提供するコンストラクタのないサブオブジェクトのみがゼロで初期化されます。 C++ 14では、Entryのstruct paddingがゼロビットに初期化されないことがあります。 (std::arrayのメンバーの後にパディングが存在する可能性があります)。同様に、std::vectorの内部に、そのコンストラクタで初期化されていないメンバーが含まれている場合。それらは初期化されずに残り、ゼロで初期化されません。

関連する問題