究竟什么是“假设”规则?

时间:2013-03-30 11:57:32

标签: c++ c optimization c++-faq as-if

正如标题所说,

  

What exactly is the "as-if" rule?

一个典型的答案是:

  

允许任何和所有代码转换不会改变程序的可观察行为的规则

我们会不时地从某些实施中获取行为,这些行为归因于此规则。好多次错了。那么,这条规则究竟是什么呢。标准没有明确地将此规则作为一个部分或段落提及,那么究竟什么属于这条规则的范围?对我来说,这似乎是一个灰色区域,标准没有详细定义。有人可以根据标准的参考资料详细说明细节吗?

注意:将其标记为C和C ++,因为它与两种语言都相关。

3 个答案:

答案 0 :(得分:85)

什么是“ as-if ”规则?

as-if ”规则基本上定义了允许在合法C ++程序上执行的实现的转换。简而言之,允许所有不影响程序“可观察行为”的转换(参见下面的精确定义)。

只要程序的行为与抽象机器方面的C ++标准指定的语义保持一致,目标就是让实现自由地执行优化。


标准在哪里引入此规则?

C ++ 11标准在第1.9 / 1段中引入了“ as-if ”规则:

  

本国际标准中的语义描述定义了参数化的非确定性摘要   机。本国际标准对符合实施的结构没有要求。   特别是,它们不需要复制或模拟抽象机器的结构。相反,符合   如上所述,实现需要模拟(仅)抽象机器的可观察行为   下方。

另外,一个解释性脚注补充说:

  

此条款有时被称为“as-if”规则,因为实施可以自由地忽略对此的任何要求   国际标准,只要结果就好像已经遵守了要求,只要可以从中确定   程序的可观察行为。例如,如果可以,实际实现不需要评估表达式的一部分   推断其价值未被使用,并且不会产生影响程序可观察行为的副作用。


该规则的具体内容是什么?

第1.9 / 5段进一步规定:

  

符合要求的实施 执行格式良好的程序应产生相同的可观察行为   作为具有相同程序的抽象机的相应实例的可能执行之一   和相同的输入。但是,如果任何此类执行包含未定义的操作,则此国际   标准不要求使用该输入执行该程序的实现(甚至不是   关于第一次未定义操作之前的操作。)

值得强调的是,当“仅执行格式良好的程序”时,此约束适用,并且执行包含未定义行为的程序的可能结果不受约束。第1.9 / 4段也明确说明了这一点:

  

本国际标准中将某些其他操作描述为未定义(例如,效果   尝试修改const对象)。 [注:本国际标准没有要求   包含未定义行为的程序的行为。 - 后注]

最后,关于“可观察行为”的定义,第1.9 / 8段如下:

  

符合实施的最低要求是:

     

- 严格按照抽象机的规则评估对volatile对象的访问。

     

- 在程序终止时,写入文件的所有数据应与其中一个可能的结果相同   根据抽象语义执行程序会产生。

     

- 交互设备的输入和输出动态应以提示的方式进行   输出实际在程序等待输入之前传送。什么构成了交互设备   是实现定义的。

     

这些统称为程序的可观察行为。 [注意:更严格   抽象和实际语义之间的对应关系可以由每个实现来定义。 - 端   注意]


是否存在此规则不适用的情况?

据我所知,“ as-if ”规则的唯一例外是复制/移动省略,即使复制构造函数,移动构造函数或析构函数也是允许的。班有副作用。确切的条件在第12.8 / 31段中规定:

  

当满足某些条件时,允许实现省略类的复制/移动构造   object,即使是为复制/移动操作选择的构造函数和/或对象的析构函数   有副作用。 [...]

答案 1 :(得分:9)

在C11中,规则永远不会被该名称调用。然而,C,就像C ++一样,用抽象机器来定义行为。 as-if规则位于C11 5.1.2.3p4 and p6

  
      
  1. 在抽象机器中,所有表达式都按语义指定进行计算。 实际实现不需要评估表达式的一部分,如果它可以推断出它的值没有被使用并且没有产生所需的副作用(包括由调用函数或访问volatile对象引起的任何副作用)。

  2.   
  3. [...]

  4.   
  5. 符合实施的最低要求是:

         
        
    • 严格按照抽象机的规则评估对volatile个对象的访问。
    •   
    • 在程序终止时,写入文件的所有数据应与根据抽象语义执行程序的结果相同。
    •   
    • 交互设备的输入和输出动态应按照7.21.3中的规定进行。这些要求的目的是尽快出现无缓冲或行缓冲输出,以确保在程序等待输入之前实际出现提示消息。
    •   
         

         

    这是该计划的可观察行为。

  6.   

答案 2 :(得分:0)

在C,C ++,Ada,Java,SML中,通过描述程序的(通常是许多可能的,不确定的)行为(暴露于I / O端口),没有明确的按条件规则

distinct 规则的一个示例是说被零除会引发异常(Ada,Caml)或空取消引用会引发异常(Java)的示例。您可以更改规则以指定 else ,然后使用另一种语言(有些人宁愿称其为“方言”(*)。有一条不同的规则可以指定)某种编程语言的独特用法(例如独特的语法规则)涵盖了一些语法构造。

(*)据某些语言学家所说的方言是一种带有“军队”的语言。在这种情况下,这可能意味着一种没有委员会和专门的编译器编辑行业的编程语言。

假设规则不是唯一规则;它没有特别涵盖任何程序,甚至也不是可以以任何方式讨论,删除或更改的规则:所谓的“规则”只是重申了程序语义已定义,并且只能根据程序执行与“外部”世界的可见交互来可移植地(通用)定义。

外部世界可以是I / O接口(stdio),GUI,甚至是交互式解释器,它可以输出纯应用语言的结果值。在C和C ++中,包括(明确指定的)对易失性对象的访问,这是另一种说法,即必须严格按照ABI(应用程序二进制接口)在内存中表示给定点上的某些对象,而不必明确提及ABI。

什么是执行跟踪的定义,也称为“可见或可观察的行为”,它定义了“假设规则”的含义。即时规则尝试进行解释,但是这样做会使人们感到困惑,而不是澄清事情,因为它表达了作为附加语义规则的表达,为实现提供了更多的回旋余地。 >

摘要:

  • 所谓的“假设规则”不会放松对实现的任何限制。
  • 您不能删除任何以可见行为(为与外部世界互动而组成的执行迹线)指定的编程语言中的准规则,以获取独特的方言。
  • 您不能将按条件规则添加到未在可见行为方面指定的任何编程语言。