在C ++ 11标准(您不再知道序列点的概念)的背景下,我想了解如何定义两个最简单的示例。
int i = 0;
i = i++; // #0
i = ++i; // #1
SO有两个主题,它们解释了C ++ 11上下文中的这些示例。这里有人说,#0
所调用UB和#1
被明确定义的。这里有人说,这两个例子是不确定的。这种含糊不清使我非常困惑。我已经阅读了三本结构良好的参考书,但是对于我来说,这个话题似乎太复杂了。
。
让我们分析示例#0
:i = i++;
。
相应的引号是:
内置后递增和后递减运算符的值计算在其副作用之前进行排序。
内置赋值运算符和所有内置复合赋值运算符的副作用(对左参数的修改)在左,右参数的值计算(但不是副作用)之后进行排序,并在排序之前赋值表达式的值计算(即,在将引用返回修改后的对象之前)
如果相对于同一标量对象上的另一个副作用,未对标量对象上的副作用进行排序,则该行为未定义。
据我所知,赋值运算符的副作用并未与其左,右参数的副作用排序。因此,赋值运算符的副作用未与的副作用排序i++
。因此#0
调用UB。
。
让我们分析示例#1
:i = ++i;
。
相应的引号是:
内置的预增和预减运算符的副作用在其值计算之前进行排序(由于定义为复合赋值,因此存在隐式规则)
内置赋值运算符和所有内置复合赋值运算符的副作用(对左参数的修改)在左,右参数的值计算(但不是副作用)之后进行排序,并在排序之前赋值表达式的值计算(即,在将引用返回修改后的对象之前)
如果相对于同一标量对象上的另一个副作用,未对标量对象上的副作用进行排序,则该行为未定义。
我看不到,这个例子与的不同之处#0
。对我来说,这似乎是UB,原因与相同#0
。赋值的副作用未与的副作用排序++i
。好像是UB。上面喜欢的主题说,它定义明确。为什么?
。
问题:如何应用引用规则来确定示例的UB。尽可能简单的解释将不胜感激。谢谢!
由于您的报价并非直接来自标准,因此我将尝试提供详细的答案,并引用标准的相关部分。在第1.9 / 12段中可以找到“副作用”和“评估”的定义:
访问由易失性glvalue(3.10)指定的对象,修改对象,调用库I / O函数或调用执行任何这些操作的函数都是副作用,它们都是执行环境状态的变化。表达式(或子表达式)的评估通常包括值计算(包括确定对象的身份以进行glvalue评估和获取先前分配给对象的值以进行prvalue评估)和副作用的初始化。
下一个相关部分是第1.9 / 15段:
除非另有说明,否则对单个运算符的操作数和单个表达式的子表达式的求值是无序列的。…………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………… 如果相对于同一标量对象上的另一副作用或使用同一标量对象的值进行的值计算,未对标量对象的副作用进行排序,则该行为未定义。
现在让我们看看如何将其应用于两个示例。
i = i++;
这是增量的后缀形式,您可以在第5.2.6段中找到其定义。最相关的句子是:
++表达式的值计算在修改操作数对象之前进行排序。
有关赋值表达式,请参见第5.17段。相关部分指出:
在所有情况下,赋值的顺序在左右操作数的值计算之后,在赋值表达式的值计算之前。
使用上面的所有信息,整个表达式的计算结果是(标准不保证该顺序!):
i++
(右侧)的值计算i
(左手边)的值计算i
(的副作用++
)的修改i
(的副作用=
)的修改所有标准保证是两个操作数的值计算在赋值表达式的值计算之前进行排序。但是,右侧的值计算只是“读取”的值,i
而不是修改i
,两个修改(副作用)没有相对于彼此排序,因此我们得到不确定的行为。
那第二个例子呢?
i = ++i;
这里的情况截然不同。您可以在第5.3.2节中找到前缀增量的定义。相关部分是:
如果x不是bool类型,则表达式++ x等效于x + = 1。
代之以,我们的表达式等于
i = (i += 1)
+=
在5.17 / 7中查找复合赋值运算符,我们得到的结果i += 1
与等效,i = i + 1
除了i
只评估一次。因此,所讨论的表达式最终变为
i =(i =(i + 1))
但是我们已经从上面知道,的值计算=
在操作数的值计算之后进行,而副作用在的值计算之前进行排序=
。因此,我们得到了明确定义的评估顺序:
i + 1
(和i
-内部表达式的左手边)的值(#1)=
,即修改“ inner”i
(i = i + 1)
,即的“新”值i
=
,即修改“外部”i
(#1):在这里,i
只计算一次,因为i += 1
等效于i = i + 1
不同的是i
仅一次(5.17 / 7)进行评价。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句