Jon*_*Mee 24 c++ arrays initializer-list language-lawyer aggregate-initialization
假设我想引用initializer_list我已定义的成员.我可以做吗?
这段代码在Visual Studio和gcc中编译并给出了预期的"13 55" ,我只想知道它是合法的:
const int foo[2] = {13, foo[0] + 42};
Run Code Online (Sandbox Code Playgroud)
Sha*_*our 20
所以我们这里有的是8.5.1C++标准草案部分所涵盖的聚合初始化,它说:
聚合是一个数组或类[...]
和:
当初始化程序列表初始化聚合时,如8.5.4中所述,初始化程序列表的元素将作为聚合成员的初始化程序,增加下标或成员顺序.每个成员都是从相应的初始化条款[...]复制初始化的.
虽然初始化聚合的每个成员的副作用应该在下一个之前进行排序似乎是合理的,因为初始化列表中的每个元素都是完整表达式.该标准实际上并不能保证我们可以从缺陷报告1343中看到这一点,该报告说:
当前的措辞并不表示非类对象的初始化是完整表达式,但可能应该这样做.
并且还注意到:
聚合初始化也可能涉及多个完整表达式,因此上面对"非类对象的初始化"的限制是不正确的.
我们可以从相关的std讨论主题中看到Richard Smith说:
[intro.execution] p10:"完整表达式是一个不是另一个表达式的子表达式的表达式.[...]如果定义了一个语言结构来产生一个函数的隐式调用,那么语言结构的使用被认为是出于这个定义的目的."
由于braced-init-list不是表达式,并且在这种情况下它不会导致函数调用,因此5和si是单独的完整表达式.然后:
[intro.execution] p14:"每个值计算和与完整表达式相关的副作用在每个值计算和与要评估的下一个全表达式相关的副作用之前都会被排序."
所以唯一的问题是,初始化si的副作用是"与"完整表达式"5"的评估"相关联"吗?我认为唯一合理的假设是:如果5正在初始化类类型的成员,那么构造函数调用显然是[intro.execution] p10中定义的完整表达式的一部分,所以很自然地假设标量类型也是如此.
但是,我不认为标准实际上明确地说明了这一点.
所以这个标准目前没有规定,不能依赖,虽然如果一个实现没有像你期望的那样对待它,我会感到惊讶.
对于像这样的简单情况,类似于此似乎是一个更好的选择:
constexpr int value = 13 ;
const int foo[2] = {value, value+42};
Run Code Online (Sandbox Code Playgroud)
该提案P0507R0:核心问题1343:非类初始化序列阐明了全表达点带来了这里,但不回答有关初始化的副作用是否包括在全表达式的计算问题.所以它没有改变,这是未指定的.
此问题的相关更改位于[intro.execution]:
组成表达式定义如下:
(9.1) - 表达式的组成表达式是该表达式.
(9.2) - braced-init-list或(可能带括号的)表达式列表的组成表达式是相应列表的元素的组成表达式.
(9.3) - form = initializer-clause的brace-or-equal-initializer的组成表达式是initializer-clause的组成表达式. [例如:
Run Code Online (Sandbox Code Playgroud)struct A { int x; }; struct B { int y; struct A a; }; B b = { 5, { 1+1 } };用于初始化b的初始化器的组成表达式是5和1 + 1. - 末端的例子]
一个完整的表达是
(12.1) - 未评估的操作数(第8条),
(12.2) - 一个常数表达式(8.20),
(12.3) - init-declarator(第11条)或mem-initializer(15.6.2),包括初始化器的组成表达式,
(12.4) - 在临时对象以外的对象的生命周期结束时生成的析构函数的调用(15.2),或者
(12.5) - 一个表达式,它不是另一个表达式的子表达式,而不是完整表达式的一部分.
因此,在这种情况下,两个13和foo[0] + 42是构成表达,它们是部分满的表达.这是对这里分析的一个突破,假设他们每个人都是他们自己的完整表达.
该指定初始化建议:p0329中包含以下除了这似乎使这个明确的:
添加一个新段落到11.6.1 [dcl.init.aggr]:
聚合元素的初始化按元素顺序进行评估.也就是说,与给定元素相关联的所有值计算和副作用在按顺序跟随它的任何元素之前排序.
我们可以看到这反映在最新的标准草案中.