13

C++11 で変数を初期化するこれら 2 つの方法に微妙な違いはありますか?

  1. vector<double> v { 0.0, 1.1, 2.2, 3.3 };

  2. vector<double> v = { 0.0, 1.1, 2.2, 3.3 };

後者は最初のものと同じすべてのケースに使用できますか?

Stroustrup はTCPL4EDで、すべてのコンテキストで使用できる唯一の方法は最初の方法であると主張し、それを推奨しています。後で、彼は、2 番目のものは 1 番目のものとは異なる書き方であるとほのめかしているようです。

4

4 に答える 4

8

1.

vector<double> v { 0.0, 1.1, 2.2, 3.3 };

direct-list-initializationです。これは、初期化子リストを取るコンストラクターで初期化されることを意味します。

コンストラクター:

vector( std::initializer_list<T> init, const Allocator& alloc = Allocator() );

2.

vector<double> v = { 0.0, 1.1, 2.2, 3.3 };

copy-list-initializationです。


標準はかなり明確です:

8.5.4 リストの初期化 [dcl.init.list]

リスト初期化は、波括弧初期化リストからのオブジェクトまたは参照の初期化です。このような初期化子は初期化子リストと呼ばれ、リストのコンマ区切りの初期化句は初期化子リストの要素と呼ばれます。初期化リストは空である可能性があります。リスト初期化は、直接初期化またはコピー初期化コンテキストで発生する可能性があります。直接初期化コンテキストでのリスト初期化は直接リスト初期化と呼ばれ、コピー初期化コンテキストでのリスト初期化はコピーリスト初期化と呼ばれます。[ 注: リストの初期化を使用できます :

  • 変数定義の初期化子として

[...]

例 :

  std::complex<double> z{1,2};

  [...]

  std::map<std::string,int> anim = { {"bear",4}, {"cassowary",2}, {"tiger",7} };

両者の違いについては、もう少し先に進む必要があります。

13.3.1.7 リスト初期化による初期化 [over.match.list]

  • direct-list-initializationの場合、候補関数はクラス T のすべてのコンストラクターです。
  • copy-list-initializationの場合、候補関数はすべて T のコンストラクターです。 ただし、explicitコンストラクターが選択された場合、初期化の形式は正しくありません。[注: この制限は、この初期化がオーバーロード解決の最終結果の一部である場合にのみ適用されます — 注釈の最後]
于 2013-08-13T17:57:43.030 に答える
1

頭に浮かぶ違いの 1 つは、最初の形式はコンストラクターが宣言されていても使用できるがexplicit、2 番目の形式は使用できないことです。申し訳ありませんが、@Timothy Shields と @Tomek は間違っています。どちらのステートメントも直接の初期化であり、初期化のコピーではありません。

于 2013-08-13T18:17:33.917 に答える
0

これは、通常のコンストラクタ (つまり、初期化子リストを使用しない) の場合と似ていると思います。最初の選択肢は、(この場合) コンストラクターを使用して、初期化子リスト コンストラクターを使用する構成です。もう 1 つの選択肢は、イニシャライザ リスト コンストラクタで作成された一時的なもので、変数はそこからコピー構築されます。一時的に消えます。後者は通常、(N)RVO が開始されるため、一時的なコピーの破棄をスキップしますが、後者の場合は、クラスが定義の時点でアクセス可能なコピー コンストラクターを持っている必要があります。少なくともこれは C++03 で覚えていることですが、C++11 では変更されている可能性があります。

于 2013-08-13T17:19:45.643 に答える