18

C++11 では、次のように "brace-or-equal-initializer" (標準の単語) を使用してクラス内の初期化を行うことができます。

struct Foo
{
  /*explicit*/ Foo(int) {}
};

struct Bar
{
  Foo foo = { 42 };
};

しかし、コメントを外すとexplicit、コンパイルされなくなります。GCC 4.7 および 4.9 は次のように述べています。

error: converting to ‘Foo’ from initializer list would use explicit constructor ‘Foo::Foo(int)’

これは驚くべきことでした。このコードがコンパイルされないのは、本当に C++11 標準の意図ですか?

=修正を削除します。Foo foo { 42 };しかし、個人的には、何十年もフォームに慣れている人にこれを説明するのは難しいと思います=。また、標準では「ブレースまたはイコールイニシャライザー」を参照しているため、古き良き方法がなぜ明らかではないこのシナリオでは機能しません。

4

3 に答える 3

13

この背後にある理論的根拠を説明することはできませんが、明白なことを繰り返すことはできます。

これは驚くべきことでした。このコードがコンパイルされないのは、本当に C++11 標準の意図ですか?

§13.3.1.7

copy-list-initialization では、明示的なコンストラクターが選択されている場合、初期化の形式が正しくありません。


= を削除すると修正されます:Foo foo { 42 };しかし、個人的には = を使用したフォームに何十年も慣れている人に説明するのは難しいと思います。このシナリオでは、古い方法は機能しません。

Foo foo { 42 }直接初期化ですが、等号 (中括弧付き) はそれをcopy-list-initialization にします。別の答えは、コンパイルがコピー初期化(中括弧なしの等号)で失敗するため、コピーリスト初期化でも失敗することは驚くべきことではありませんが、2つは異なる理由で失敗するという理由です。

cppリファレンス:

直接初期化は、コピー初期化よりも寛容です。コピー初期化では、非明示的なコンストラクターとユーザー定義の変換関数のみが考慮されますが、直接初期化では、すべてのコンストラクターと暗黙的な変換シーケンスが考慮されます。

そして、明示的な指定子に関する彼らのページ:

暗黙的な変換またはコピー初期化を許可しないコンストラクターおよび(C++11 以降)変換演算子を指定します。

一方、copy-list-initialization の場合:

T オブジェクト= {引数1 、引数2 、... }; (10)

10) 等号の右側 (コピー初期化と同様)

  • それ以外の場合、T のコンストラクターは 2 つのフェーズで考慮されます。

    • 前のステージで一致が生成されない場合、T のすべてのコンストラクターは、braced-init-list の要素で構成される引数のセットに対するオーバーロードの解決に参加します。ただし、非縮小変換のみが許可されるという制限があります。この段階で、copy-list-initialization に最適な明示的なコンストラクターが生成される場合、コンパイルは失敗します (単純な copy-initialization では、明示的なコンストラクターはまったく考慮されないことに注意してください)。

copy-list-initialization で明示的なコンストラクターが許可されている場合、何が問題になる可能性があるで説明したように? 、明示的なコンストラクターが選択されていますが、使用が許可されていないため、コンパイルは失敗します。

于 2014-10-01T09:13:12.410 に答える
12

の場合、これFoo(int)explicitコンパイルされません:

Foo foo = 42;

したがって、「何十年も with のフォームに慣れてきた人」にとっては、 with のフォームがコンパイル=されないことも驚くことではありません。{}

于 2014-10-01T09:22:05.240 に答える
7

ウィジェット w = {x};

これを「コピーリストの初期化」と呼びます。ウィジェット w{x}; と同じ意味です。ただし、明示的なコンストラクターは使用できません。単一のコンストラクターのみが呼び出されることが保証されています。

http://herbsutter.com/2013/05/09/gotw-1-solution/より

オブジェクトを初期化するさまざまな方法の詳細については、この記事の残りの部分を参照してください。

于 2014-10-01T09:13:30.597 に答える