C ++ 11直接列表初始化语法

时间:2013-02-27 20:49:52

标签: c++ opengl-es c++11 initialization

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

我已经知道(并经常实现)传统的C样式结构初始化,使用以下语法来初始化POD,例如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类型使用的联合/结构布局的性质使编译器混淆。

在进一步实现代码之前,对这种奇怪语法的一些澄清将非常感激

2 个答案:

答案 0 :(得分:3)

外部大括号分隔对象本身的初始化程序,内部大括号是对象内部成员的初始化程序,例如。

GLKVector2 v = { initializers-for-members };

其中initializers-for-members{ 0, 0 },因为该类型具有两个元素的数组成员,并使用{ a, b }初始化包含两个成员的数组。

C ++支持“大括号”(8.5.1 [dcl.init.aggr]第11段),这意味着在某些情况下可以将嵌套大括号排除在初始化程序之外,但在C ++ 11中,只允许使用大括号。副本初始化。这就是为什么你不需要两组大括号用于copy-init的情况,但确实需要它们用于direct-init。

由于C ++ 11已经完成,DR 1270已经更改了规则,以便在直接列表初始化的情况下允许括号省略,但这是对后C ++ 11草案的更改和尚未得到广泛支持。

答案 1 :(得分:2)

根据docs 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数组。

你应该看看aggregate initialization

修改

实际上,查看文档时,可能会感兴趣的是关于大括号(仅允许在复制初始化上下文中)的规则。