Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我可以引用初始值设定项列表中以前的成员吗?_C++_Arrays_Language Lawyer_Initializer List_Aggregate Initialization - Fatal编程技术网

C++ 我可以引用初始值设定项列表中以前的成员吗?

C++ 我可以引用初始值设定项列表中以前的成员吗?,c++,arrays,language-lawyer,initializer-list,aggregate-initialization,C++,Arrays,Language Lawyer,Initializer List,Aggregate Initialization,假设我想引用我已经定义的初始值设定项列表的成员。我能做吗 这段代码在Visual Studio中编译并给出了预期的“13 55”,我只想知道它是合法的: const int foo[2] = {13, foo[0] + 42}; 我们这里有C++标准草案的代码< 8.5.1部分所涵盖的集合初始化,它表示: 聚合是数组或类[…] 以及: 当聚合由初始值设定项列表初始化时,如指定 在8.5.4中,初始值设定项列表的元素如下所示: 聚合成员的初始值设定项,下标递增 或会员订单。每个成员都是从 相应的

假设我想引用我已经定义的
初始值设定项列表的成员。我能做吗

这段代码在Visual Studio中编译并给出了预期的“13 55”,我只想知道它是合法的:

const int foo[2] = {13, foo[0] + 42};

我们这里有C++标准草案的代码< 8.5.1部分所涵盖的集合初始化,它表示:

聚合是数组或类[…]

以及:

当聚合由初始值设定项列表初始化时,如指定 在8.5.4中,初始值设定项列表的元素如下所示: 聚合成员的初始值设定项,下标递增 或会员订单。每个成员都是从 相应的初始值设定项子句[…]

尽管初始化聚合的每个成员的副作用应该在下一个之前排序似乎是合理的,因为初始化列表中的每个元素都是完整表达式。该标准实际上并不保证这一点,我们可以从中看出:

当前的措辞并不表示非类对象的初始化是一个完整表达式,但可能应该这样做

并注意到:

聚合初始化还可能涉及多个完整表达式,因此上面对“非类对象的初始化”的限制是不正确的

我们可以从一个相关的例子中看到理查德·史密斯说:

[intro.execution]p10:“完整表达式是一个不完整的表达式 另一表达式的子表达式。[…]如果是语言构造 定义为生成函数的隐式调用,使用 语言结构被认为是一个表达的目的 这是定义的一部分。”

因为带括号的init列表不是表达式,在本例中 不会导致函数调用,5和s.i是分开的 完整的表达。然后:

[intro.execution]第14页:“每个值的计算和副作用 与完整表达式关联的每个值都在每个值之前排序 与下一个完整表达式关联的计算和副作用 待评估。”

所以唯一的问题是,初始化s.i 与“评估”关联的完整表达“5”?我想 唯一合理的假设是:如果5正在初始化 类类型的成员,构造函数调用显然是 完整表达式由[intro.execution]p10中的定义定义定义,因此 很自然地假设标量类型也是如此

然而,我认为标准并没有明确说明这一点 任何地方

因此,该标准目前没有规定这一点,也不能依赖它,尽管如果实现没有按照您期望的方式处理它,我会感到惊讶

对于这样一个简单的案例,类似的东西似乎是更好的选择:

constexpr int value = 13 ;
const int foo[2] = {value, value+42};
C++17中的变化 说明了提出的完整表达式点,但没有回答有关完整表达式的评估中是否包含初始化的副作用的问题。所以这并没有改变,这是未指定的

这一问题的相关变化如下:

组成表达式的定义如下:

(9.1)-表达式的组成表达式就是该表达式

(9.2)-带括号的init列表或(可能带括号的)表达式列表的组成表达式为 各列表元素的组成表达式

(9.3)大括号或同等形式的初始值设定项的组成表达式为 初始值设定项子句的组成表达式。 [示例:

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)初始声明人(第11条)或mem初始值设定人(15.6.2),包括 初始值设定项,

(12.4)-在对象生命周期结束时生成的析构函数调用,而不是临时函数 对象(15.2),或

(12.5)-不是另一个表达式的子表达式且不是另一个表达式的一部分的表达式 充分表达


因此在这种情况下,
13
foo[0]+42
都是组成表达式,是完整表达式的一部分。这是一个突破,从假设,他们每个人都将是自己的完整表达

C++20中的变化 包含以下添加项,这似乎使其定义明确:

在11.6.1[dcl.init.aggr]中添加新段落:

聚合元素的初始化按元素顺序进行计算。就是, 与给定元素相关的所有值计算和副作用都按顺序排列在其后任何元素的值计算和副作用之前


我们可以看到这反映在。

@NathanOliver谢谢,我同意。但这是一个完全不同的问题。阅读有关结构的内容,找到关于数组的答案是没有建设性的。DR1343看起来还不够深入;需要的是一个绝对语句,对于聚合初始化,在前一个元素的初始化完成之前,不能对初始化器求值。正如沙菲克所说,目前似乎没有任何措辞阻止对列表中的所有元素进行评估,然后将结果应用于聚合。这是一个带括号的init列表,而不是一个
初始值设定项\u list
,不是吗?@BaummitAugen@NathanOliver哇。。。我是哑巴。谢谢你的链接。你呢?它说得相当清楚