本文介绍了我可以引用初始化列表的先前成员吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说我想引用我已经定义的initializer_list的成员.我可以吗?

Say I want to refer to a member of an initializer_list that I already defined. Can I do it?

此代码编译并给出预期的结果:我在Visual Studio和 gcc 中均给出了"13 55"只是想知道这是合法的:

This code compiles and gives the expected: "13 55 " in both Visual Studio and gcc, I'd just like to know that it's legal:

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

推荐答案

所以我们这里是C ++标准草案的8.5.1部分所涉及的聚合初始化,它说:

So what we have here is aggregate initialization covered in section 8.5.1 of the draft C++ standard and it says:

和:

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

Although it seems reasonable that side effects from initializing each member of the aggregate should be sequenced before the next, since each element in the initializer list is a full expression. The standard does not actually guarantee this we can see this from defect report 1343 which says:

并注意:

,我们可以从相关的标准讨论话题理查德·史密斯说:

and we can see from a related std-discussion topic Richard Smith says:

由于braced-init-list不是表达式,在这种情况下,它是一个表达式 不会导致函数调用,因此5和s.i是分开的 完整的表情.然后:

Since a braced-init-list is not an expression, and in this case it does not result in a function call, 5 and s.i are separate full-expressions. Then:

[intro.execution] p14:每个值的计算和副作用 与全表达式关联的值在每个值之前进行排序 与下一个完整表达式相关的计算和副作用 待评估."

[intro.execution]p14: "Every value computation and side effect associated with a full-expression is sequenced before every value computation and side effect associated with the next full-expression to be evaluated."

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

So the only question is, is the side-effect of initializing s.i "associated with" the evaluation of the full-expression "5"? I think the only reasonable assumption is that it is: if 5 were initializing a member of class type, the constructor call would obviously be part of the full-expression by the definition in [intro.execution]p10, so it is natural to assume that the same is true for scalar types.

但是,我认为标准实际上并没有明确说明这一点 任何地方.

However, I don't think the standard actually explicitly says this anywhere.

因此,该标准目前尚未指定,因此无法依赖,尽管如果实现未按您期望的方式处理它,我会感到惊讶.

So this is currently not specified by the standard and can not be relied upon, although I would be surprised if an implementation did not treat it the way you expect.

对于像这样的简单情况,类似的东西似乎是更好的选择:

For a simple case like this something similar to this seems a better alternative:

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

C ++ 17中的更改

提案P0507R0:核心问题1343 :非类初始化的排序阐明了此处,但没有回答关于初始化的副作用是否包括在全表达式的评估中的问题.因此,未指定它不会改变.

Changes In C++17

The proposal P0507R0: Core Issue 1343: Sequencing of non-class initialization clarifies the full-expression point brought up here but does not answer the question about whether the side-effect of initialization is included in the evaluation of the full-expression. So it does not change that this is unspecified.

此问题的相关更改位于 [intro.execution] :

The relevant changes for this question are in [intro.execution]:

(9.1)—表达式的组成表达式是该表达式.

(9.1) — The constituent expression of an expression is that expression.

(9.2)-括号初始列表或(可能带有括号的)表达式列表的组成表达式为 各个列表元素的组成表达式.

(9.2) — The constituent expressions of a braced-init-list or of a (possibly parenthesized) expression-list are the constituent expressions of the elements of the respective list.

(9.3)— 形式为=初始化子句的括号或相等初始化器的组成表达式为 初始化子句的组成表达式. [示例:

(9.3) — The constituent expressions of a brace-or-equal-initializer of the form = initializer-clause are the constituent expressions of the initializer-clause. [ Example:

struct A { int x; };
struct B { int y; struct A a; };
B b = { 5, { 1+1 } };

用于b初始化的初始化器的组成表达式为5和1 + 1 . —完示例]

The constituent expressions of the initializer used for the initialization of b are 5 and 1+1. —end example ]

[intro.execution] p12 :

(12.1)-未计算的操作数(第8条),

(12.1) — an unevaluated operand (Clause 8),

(12.2)-常量表达式(8.20),

(12.2) — a constant-expression (8.20),

(12.3)-初始化声明程序(第11节)或mem初始化程序(15.6.2),包括 初始化程序,

(12.3) — an init-declarator (Clause 11) or a mem-initializer (15.6.2), including the constituent expressions of the initializer,

(12.4)-调用除临时对象以外的对象生命周期结束时生成的析构函数 对象(15.2),或

(12.4) — an invocation of a destructor generated at the end of the lifetime of an object other than a temporary object (15.2), or

(12.5)—一个表达式,它不是另一个表达式的子表达式,并且不属于a的一部分 充分表达.

(12.5) — an expression that is not a subexpression of another expression and that is not otherwise part of a full-expression.

因此,在这种情况下,13foo[0] + 42均为组成表达式,它们是 full-expression 的一部分.这与此处的分析假定它们每个都是自己的完整表达式.

So in this case both 13 and foo[0] + 42 are constituent expression which are part of a full-expression. This is a break from the analysis here which posited that they would each be their own full-expressions.

指定的初始化建议:P0329 包含以下补充内容,似乎可以对它进行明确定义:

The Designated Initialization proposal: P0329 contains the following addition which seems to make this well defined:

按元素顺序评估聚合元素的初始化.那是, 与给定元素关联的所有值计算和副作用均按顺序排列在其后的任何元素的计算之前.

The initializations of the elements of the aggregate are evaluated in the element order. That is, all value computations and side effects associated with a given element are sequenced before those of any element that follows it in order.

我们可以看到,这反映在最新标准草案.

We can see this is reflected in the latest draft standard.

这篇关于我可以引用初始化列表的先前成员吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!