如何确定在其他人之前“排序”的内容?

时间:2012-03-05 06:37:01

标签: c++ c++11 language-lawyer

关于C ++ 11中的Undefined Behavior和Sequenced [Before / After]关系,我经历了this excellent answer。我理解二元关系概念,但我不知道管理测序的新规则是什么。

对于这些熟悉的示例,排序规则如何应用?

  1. i = ++i;
  2. a[++i] = i;
  3. 更具体地说,新的C ++ 11排序规则是什么?

    我正在寻找一些类似的规则(这一个是完全组成的)

      

    lhs语句的'='始终在rhs之前排序,因此首先进行评估。

    如果这些标准本身可用,有人可以在这里引用相同的内容吗?

1 个答案:

答案 0 :(得分:6)

在我看来,这比规则点的旧规则要复杂得多,而且我并非100%肯定我理解正确...无论如何,IIUC这一切归结为如果能得到你需要的价值副作用已经应用。

第一种情况

i = ++i;

这里要进行分配,你需要正确部分的值,要获得该值,你需要已经应用副作用;因此,这里的分配在增量后排序,一切都很好。这里重要的一点是,要完成任务,您需要RHS的值,只需要LHS的地址

回顾一下:

  1. 分配在&i++i
  2. 之后排序
  3. ++i在增量
  4. 之后排序
  5. (传递性)分配在增量后进行排序
  6. i的值在增量后只读取一次。它被写入两次,一次是增量,一次是赋值,但这两个操作是按顺序排序的(首先是增量,然后是赋值)。

    第二种情况

    a[++i] = i;
    

    在此,您需要RHS的i值和LHS的++i值。但是这两个表达式没有排序(赋值运算符没有强制执行排序),因此结果未定义。

    回顾一下:

    1. 分配在&a[++i]i
    2. 之后排序
    3. &a[++i]++i
    4. 之后排序
    5. ++i在增量
    6. 之后排序

      这里i的值被读取两次,一次是LHS的赋值,一次是RHS。 LHS部分也进行了修改(增量)。然而,这种写访问和赋值RHS的读访问不是相互排序的,因此这个表达式是UB。

      最后的咆哮

      让我再说一遍,我不确定我刚才所说的内容......我的强烈意见是,这种新方法在前后方法中难以理解。新的规则有希望只能使一些UB之前的表达式得到很好的定义(并且UB是最糟糕的结果),但它也使得规则更加复杂(它只是“不要在序列点之间改变两次相同的事情” “......你不必做一个心理拓扑排序来猜测某些东西是不是UB。”

      从某种意义上说,新规则没有对C ++ 程序造成损害(UB是敌人,现在该区域的UB较少)但对语言造成了损害>通过增加复杂性(并确保C ++不需要的东西增加了复杂性)。

      另请注意,有关++i的有趣之处在于返回的值是l值(这就是++ ++ i合法的原因),所以它基本上是一个地址,逻辑上不需要返回值在增量后排序。但标准是这样说的,这是你需要燃烧到神经元的规则。当然要有一个“可用的”++i,你希望值的用户获得更新的值,但仍然只要++运算符看到的东西(它返回一个不受其影响的地址)增量)这个测序不是正式需要。

      使用新规则,您不仅需要进行心理拓扑排序以查看表达式是否有效,而且还需要使用您需要记忆的任意序列关系来执行此操作。

      当然,作为一名程序员,你希望永远不会编写多次改变相同值的代码而没有清晰的序列,但是你仍然会遇到其他程序员编写的代码中的错误...明确,你现在需要更加努力地去理解是否有合法的C ++。