6

初期化リストについてので、Stroustrupは基本的に、中括弧を使用した新しい構築構文は、以前のすべての構築構文の一般的な置き換えになるはずだと言っていることを理解しました。

X x1(); // most vexing parse ... doesn't work as intended
X x2(x1);
X x3 = x1;
X x4 = X();

代わりに、新しい構文は、あらゆる状況で使用できる可能な代替として一律に使用されることになっています...繰り返しますが、それは私が彼の話から取ったコアメッセージです。多分私は彼を誤解した。

それで、問題は、この構文がどれほど一般的かということです。新しいC++11コードで古いスタイルの構造を使用しないことは可能ですか、それとも元に戻さなければならない状況がありますか?


この質問は、コンパイラのエラーであると思われる次のエラーが発生したときにトリガー/動機付けられました(ただし、修正できれば幸いです)。

struct X {};

int main() {
  X x;
  X& y{x}; // works with (x)
  X& z{y}; // works with (y)
}

これはg++4.7.1でもコンパイルされず、 ideoneの4.5.1でもコンパイルされません。

prog.cpp: In function 'int main()':
prog.cpp:5:9: error: invalid initialization of non-const reference of type 'X&' from an rvalue of type '<brace-enclosed initializer list>'
prog.cpp:6:9: error: invalid initialization of non-const reference of type 'X&' from an rvalue of type '<brace-enclosed initializer list>'

に置き換えるXと機能することに注意してくださいint

4

1 に答える 1

9

ブレースの初期化は、初期化子が使用されているすべての場所で機能します。ブレース初期化子がアクセスできないコンストラクターにアクセスするためにparensを使用する必要がある場合がありますが、それらはまれです。

std::vector<int> v(1,1);
std::vector<int> v{1,1};

vector<int>たまたま2秒かかる特殊なコンストラクターがあるintため、2秒の長さのベクトルを作成しようとするとあいまいになりintます。あいまいなコンストラクターは、下位​​互換性のためにのみ存在します。新しいクラスは、initializer_listと競合するコンストラクターで定義しないでください。

あいまいさは、中括弧の初期化構文が、他の方法では一致する他のコンストラクターよりもinitializer_listコンストラクターを優先するという事実によって解決されます。non-initializer_listコンストラクターを使用してあいまいさを解決したい場合は、中括弧の初期化を使用できません。


ビャーネ・ストロヴルプはこう書いています

{}初期化の統一的な使用はC++11でのみ可能になったため、古いC ++コードは()と=初期化を使用します。したがって、()と=の方がわかりやすいかもしれません。ただし、要素のリストとコンストラクター引数のリストを使用した初期化を区別する必要があるまれな場合を除いて、()表記を優先する論理的な理由はわかりません。

                                                         — C ++プログラミング言語、第4版§17.3.2.1


サンプルコードは完全に合法であり、期待どおりに機能するはずです。発生するエラーは、GCCのバグにすぎません。ClangとVC++2012はどちらもコードを受け入れます。

于 2012-09-16T20:03:37.320 に答える