关于C ++ 11中的Undefined Behavior和Sequenced [Before / After]关系,我经历了this excellent answer。我理解二元关系概念,但我不知道管理测序的新规则是什么。
对于这些熟悉的示例,新排序规则如何应用?
i = ++i;
a[++i] = i;
更具体地说,新的C ++ 11排序规则是什么?
我正在寻找一些类似的规则(这一个是完全组成的)
lhs
语句的'='
始终在rhs
之前排序,因此首先进行评估。
如果这些标准本身可用,有人可以在这里引用相同的内容吗?
答案 0 :(得分:6)
在我看来,这比规则点的旧规则要复杂得多,而且我并非100%肯定我理解正确...无论如何,IIUC这一切归结为如果能得到你需要的价值副作用已经应用。
i = ++i;
这里要进行分配,你需要正确部分的值,要获得该值,你需要已经应用副作用;因此,这里的分配在增量后排序,一切都很好。这里重要的一点是,要完成任务,您需要RHS的值,只需要LHS的地址。
回顾一下:
&i
和++i
++i
在增量 i
的值在增量后只读取一次。它被写入两次,一次是增量,一次是赋值,但这两个操作是按顺序排序的(首先是增量,然后是赋值)。
a[++i] = i;
在此,您需要RHS的i
值和LHS的++i
值。但是这两个表达式没有排序(赋值运算符没有强制执行排序),因此结果未定义。
回顾一下:
&a[++i]
和i
&a[++i]
在++i
++i
在增量这里i
的值被读取两次,一次是LHS的赋值,一次是RHS。 LHS部分也进行了修改(增量)。然而,这种写访问和赋值RHS的读访问不是相互排序的,因此这个表达式是UB。
让我再说一遍,我不确定我刚才所说的内容......我的强烈意见是,这种新方法在前后方法中难以理解。新的规则有希望只能使一些UB之前的表达式得到很好的定义(并且UB是最糟糕的结果),但它也使得规则更加复杂(它只是“不要在序列点之间改变两次相同的事情” “......你不必做一个心理拓扑排序来猜测某些东西是不是UB。”
从某种意义上说,新规则没有对C ++ 程序造成损害(UB是敌人,现在该区域的UB较少)但对语言造成了损害>通过增加复杂性(并确保C ++不需要的东西增加了复杂性)。
另请注意,有关++i
的有趣之处在于返回的值是l值(这就是++ ++ i
合法的原因),所以它基本上是一个地址,逻辑上不需要返回值在增量后排序。但标准是这样说的,这是你需要燃烧到神经元的规则。当然要有一个“可用的”++i
,你希望值的用户获得更新的值,但仍然只要++
运算符看到的东西(它返回一个不受其影响的地址)增量)这个测序不是正式需要。
使用新规则,您不仅需要进行心理拓扑排序以查看表达式是否有效,而且还需要使用您需要记忆的任意序列关系来执行此操作。
当然,作为一名程序员,你希望永远不会编写多次改变相同值的代码而没有清晰的序列,但是你仍然会遇到其他程序员编写的代码中的错误...明确,你现在需要更加努力地去理解是否有合法的C ++。