2

リストの初期化とそのさまざまなフレーバーを読んだ後、XcodeとObjective-C ++を使用して作成しているopenGLESアプリのいくつかの機能を、かなりあいまいなものに遭遇するまでテストすることにしました。

GLKVector2などのPODを初期化するために次の構文を使用する従来のCスタイルの構造体の初期化について知っています(そして頻繁に実装します)。

GLKVector2 point = { 0,0 };    //copy-initialized

ただし、このアプローチは、プログラマーが意図したものであるとは限りません。したがって、割り当て(および不要なコピー構築操作)を削除して、直接初期化を優先すると、(ドキュメントから)上記の宣言は次のように表示されると想定されます。

GLKVector2 point{ 0,0 };    //direct-initialized, but generates compile error

ただし、コードが次のようになっている場合、コンパイラは文句を言いません。

GLKVector2 point{ { 0,0 } };

私には、これpointは内部構造から作成された一時的なものから直接初期化されている{ 0,0 }ように見え、したがって最初のアプローチに勝る利点はありません。一時的なものは、割り当てと割り当て解除を行う必要があります。

あるいは、おそらくこの問題は、コンパイラを混乱させるGLKit型によって使用されるunion/structレイアウトの性質にすぎません。

コードにさらに実装する前に、この奇妙な構文についていくつか説明していただければ幸いです。

4

2 に答える 2

3

外側の中括弧はオブジェクト自体の初期化子を区切り、内側の中括弧はオブジェクト内のメンバーの初期化子です。

GLKVector2 v = { initializers-for-members };

これは、型に2つの要素の配列メンバーがあり、2つのメンバーの配列を。で初期化するためinitializers-for-membersです。{ 0, 0 }{ a, b }

C ++は「中括弧の省略」(8.5.1 [dcl.init.aggr]段落11)をサポートします。つまり、特定の状況では、ネストされた中括弧を初期化子から除外できますが、C ++ 11では、中括弧の省略はコピー初期化でのみ許可されます。 。これが、copy-initの場合には2セットの中括弧は必要ありませんが、direct-initの場合には中括弧が必要な理由です。

C ++ 11が完了してから、 DR 1270によってルールが変更され、直接リスト初期化の場合にも中括弧を省略できるようになりましたが、これはC ++ 11以降のドラフトに加えられた変更であり、まだ広くサポートされていません。

于 2013-02-28T18:28:12.533 に答える
2

ドキュメント によるGLKVector2と:

union _GLKVector2
   {
   struct { float x, y; };
   struct { float s, t; };
      float v[2];
};
typedef union _GLKVector2 GLKVector2;

そのため、二重中括弧が必要です。ユニオンメンバーを初期化することで初期化しています。メンバーごとの集計初期化はインプレースで行われます。それがフラットな構造である場合、中括弧の仮定は機能します。std::arrayこれは、 (たとえば)を初期化するときにも発生します。これはstd::array<int, 2> a{{1, 2}}、PODアグリゲートであり、一時的なC配列が含まれていないためです。

集約の初期化を確認する必要があります。

編集

実際、ドキュメントを調べると、中括弧の省略(コピー初期化のコンテキストでのみ許可されている)に関するルールがあり、興味深い場合があります。

于 2013-02-27T21:47:46.237 に答える