2

在阅读了列表初始化及其各种风格之后,我决定在我使用 Xcode 和 Objective-C++ 编写的 openGL ES 应用程序中测试一些功能,直到遇到一些相当模糊的东西。

我知道(并且经常实现)使用以下语法初始化 POD 的传统 C 样式结构初始化,例如 GLKVector2:

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

The outer braces delimit the initializer for the object itself, the inner braces are the initializer for a member inside the object, e.g.

GLKVector2 v = { initializers-for-members };

where initializers-for-members is { 0, 0 } because the type has an array member, of two elements, and you initialize an array of two members with { a, b }.

C++ supports "brace elision" (8.5.1 [dcl.init.aggr] paragraph 11) which means nested braces can be left out of the initializer under certain circumstances, but in C++11 brace elision is only allowed for copy-initialization. This is why you don't need two sets of braces for the copy-init case, but do need them for direct-init.

Since C++11 was completed the rules have been changed by DR 1270 to allow brace elision in the direct-list-initialization case too, but that's a change made to the post-C++11 draft and not widely supported yet.

于 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 回答