C ++ 11中的新序列点 [英] New Sequence Points in C++11
问题描述
新学年即将来临。
我们已经开始接受为什么 ++ i ++
不能正常工作的标准
With the new college year upon us.
We have started to receive the standard why does ++ i ++
not work as expected questions.
在回答了其中一种类型的问题后,我被告知新的C ++ 11标准已更改,这不再是未定义的行为。我听说序列点
已被之前
和取代c $ c>,但没有深入(或根本没有)研究这个主题。
After just answering one of these type of questions I was told that the new C++11 standard has changed and this is no longer undefined behavior. I have heard that sequence points
have been replaced by sequenced before
and sequenced after
but have not read deep (or at all) into the subject.
所以我刚才回答的问题是:
So the question I was just answering had:
int i = 12;
k = ++ (++ i);
所以问题是:
如何在C ++ 11中具有顺序点更改,它如何影响上述问题。
How has the sequence points changes in C++11 and how does it affect questions like the above. Is it still undefined behavior or is this now well defined?
推荐答案
在这种情况下,UB是基于[intro.execution]的? / 15
The UB in those cases is based on [intro.execution]/15
除非另有说明,否则对单个运算符的操作数和单个表达式的子表达式的求值是无序列的。运算符的操作数的计算在运算符结果的值计算之前进行排序。如果相对于同一标量对象上的另一副作用或使用同一标量对象的值进行的值计算,未对标量对象的副作用进行排序,则行为未定义。
Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced. [...] The value computations of the operands of an operator are sequenced before the value computation of the result of the operator. If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined.
对于 ++(++ i)
:[expr.pre.incr] / 1指出 ++ i
定义为 i + = 1
。这导致[expr.ass] / 1,它表示
For ++(++i)
: [expr.pre.incr]/1 states that ++i
is defined as i+=1
. This leads to [expr.ass]/1, which says
在所有情况下,赋值都在右边的值计算之后进行排序和左操作数,并在赋值表达式的值计算之前。
In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression.
因此,对于 ++(+ + i)
,等效于(i + = 1)+ = 1
,内部分配在外部分配之前排序,我们没有UB
Therefore, for ++(++i)
, equivalent to (i+=1)+=1
, the inner assignment is sequenced before the outer assignment, and we have no UB.
[intro.execution] / 15有一个UB的示例:
[intro.execution]/15 has an example of UB:
i = i++ + 1; // the behavior is undefined
这种情况有点不同(感谢 Oktalist 指出此处的前后错误)。 [expr.post.incr] / 1描述了后缀增量的影响。它指出:
The case here is a bit different (thanks to Oktalist for pointing out a pre/postfix mistake here). [expr.post.incr]/1 describes the effects of postfix increment. It states:
++
表达式的值计算在修改操作数对象。
The value computation of the
++
expression is sequenced before the modification of the operand object.
但是,对副作用的排序没有要求( i
的修改)。分配表达式也可以施加这样的要求。但是赋值表达式只需要在赋值之前对操作数的值计算(而不是副作用)进行排序。因此,通过 i = ..
和 i ++
进行的两个修改是无序列的,并且我们得到的行为不确定。
However, there is no requirement on the sequencing of the side effect (the modification of i
). Such a requirement could also be imposed by the assignment-expression. But the assignment-expression only requires the value computations (but not the side effects) of the operands to be sequenced before the assignment. Therefore, the two modifications via i = ..
and i++
are unsequenced, and we get undefined behaviour.
NB i =(i = 1);
确实没有相同的问题:内部赋值保证 i的副作用= 1
在相同表达式的值计算之前进行排序。并且该值是外部分配所必需的,这保证了它(右操作数(i = 1)
的值计算)在外部分配的副作用之前进行排序。分配。同样, i = ++ i + 1;
(相当于 i =(i + = 1)+ 1;
)
N.B. i = (i = 1);
does not have the same problem: The inner assignment guarantees the side effect of i = 1
is sequenced before the value computation of the same expression. And the value is required for the outer assignment, which guarantees that it (the value computation of the right operand (i = 1)
) is sequenced before the side effect of the outer assignment. Similarly, i = ++i + 1;
(equivalent to i = (i+=1) + 1;
) has defined behaviour.
逗号运算符是对副作用进行排序的一个示例; [expr.comma] / 1
The comma operator is an example where the side effects are sequenced; [expr.comma]/1
与左表达式相关的每个值计算和副作用都在与每个相关的值计算和副作用之前进行排序
Every value computation and side effect associated with the left expression is sequenced before every value computation and side effect associated with the right expression.
[intro.execution] / 15包括示例 i = 7,i ++, i ++;
(读取:(i = 7),i ++,i ++;
),这是定义的行为( i
变为 9
)。
[intro.execution]/15 includes the example i = 7, i++, i++;
(read: (i=7), i++, i++;
), which is defined behaviour (i
becomes 9
).
这篇关于C ++ 11中的新序列点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!