14

C++11 で新しい統一初期化構文をいつ、どのように使用すればよいかわかりません。
たとえば、次のようになります。

std::string a{"hello world"}; // OK
std::string b{a};  // NOT OK

2番目のケースで機能しないのはなぜですか? エラーは次のとおりです。

error: no matching function for call to ‘std::basic_string<char>::basic_string(<brace enclosed initializer list>)’    

このバージョンの g++ でg++ (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2

また、プリミティブ データでは、どの構文を使用すればよいでしょうか?

int i = 5;
int i{5};
int i = {5};
4

3 に答える 3

20

のコンパイルエラー

// T t{u};
std::string a;
std::string b{a};

4つのものの組み合わせです

  • 少し前までのドラフトでTは、初期化子リストコンストラクター(要素std::stringを取得するコンストラクターが1つある場合char)がある場合、初期化子リスト自体が引数として渡されると述べられていました。したがって、コンストラクターへの引数はではなくa、です{a}

  • ドラフトでは、参照を初期化する初期化子リストは、直接バインドではなく、最初に初期化子リストの要素から一時を作成し、次にターゲット参照をその一時にバインドすることによって実行されると述べています。

  • ドラフトでは、初期化子リストによって参照を初期化するとき、参照の初期化が直接バインドされていないとき、変換シーケンスはユーザー定義の変換シーケンスであると述べています。

  • ドラフトでは、上記のようなコンテキストで過負荷解決シナリオでクラスのコンストラクターを候補として検討するときに初期化子リスト自体を渡すときX、次に「cv Xへの参照」タイプの最初のコンストラクターパラメーターを検討するとき(cv = const / volatile )-言い換えると、コピーまたは移動コンストラクターである可能性が高いため、ユーザー定義の変換は許可されません。そうでなければ、そのような変換が許可される場合、リストの初期化ではネストされたユーザー定義の変換が1つだけに制限されないため、常にあいまいな状態で実行できます。

上記のすべての組み合わせは、コンストラクターを使用して。を取得できないこと{a}です。を使用initializer_list<char>しているものは一致せず、を使用している他のものstring&&const string&禁止されています。これは、パラメータをにバインドするためにユーザー定義の変換が必要になるため{a}です。

最近のドラフトで最初のルールが変更されたことに注意してください。初期化リストコンストラクターが初期化リストを取得できない場合、引数リストは初期化リストのすべての要素で構成されると言われています。この更新されたルールを使用すると、サンプルコードは正常に機能します。

于 2011-09-30T16:40:04.293 に答える
10

最初の例は、コピー コンストラクターを呼び出して動作するはずです。GCC を使用している場合、これは 4.6 で修正されています。

最後の例には、スタイル以外のわずかな違いがあります。

int i = 5.0;   // fine, stores 5
int i{5.0};    // won't compile!
int i = {5.0}; // won't compile!

違いは、統一された初期化構文では縮小変換が許可されないことです。それらを選択するときは、このことを考慮に入れることをお勧めします。

于 2011-09-30T16:15:56.510 に答える
4

セミコロンを忘れたため、機能しません。

std::string b{a};
               ^^^

それ以外の場合、この構文は問題なく、コピーコンストラクターを呼び出します。

2番目の質問では、int i{5};均一にしたい場合に使用しますint i = 5;が、おそらく読みやすくなります。

于 2011-09-30T14:48:20.017 に答える