在阅读了列表初始化及其各种风格之后,我决定在使用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类型使用的联合/结构布局的性质使编译器混淆。
在进一步实现代码之前,对这种奇怪语法的一些澄清将非常感激
答案 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。
实际上,查看文档时,可能会感兴趣的是关于大括号(仅允许在复制初始化上下文中)的规则。