正如标题所说,
一个典型的答案是:
允许任何和所有代码转换不会改变程序的可观察行为的规则
我们会不时地从某些实施中获取行为,这些行为归因于此规则。好多次错了。那么,这条规则究竟是什么呢。标准没有明确地将此规则作为一个部分或段落提及,那么究竟什么属于这条规则的范围?对我来说,这似乎是一个灰色区域,标准没有详细定义。有人可以根据标准的参考资料详细说明细节吗?
注意:将其标记为C和C ++,因为它与两种语言都相关。
答案 0 :(得分:85)
“ 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:
在抽象机器中,所有表达式都按语义指定进行计算。 实际实现不需要评估表达式的一部分,如果它可以推断出它的值没有被使用并且没有产生所需的副作用(包括由调用函数或访问volatile对象引起的任何副作用)。
[...]
- 醇>
符合实施的最低要求是:
- 严格按照抽象机的规则评估对
volatile
个对象的访问。- 在程序终止时,写入文件的所有数据应与根据抽象语义执行程序的结果相同。
- 交互设备的输入和输出动态应按照7.21.3中的规定进行。这些要求的目的是尽快出现无缓冲或行缓冲输出,以确保在程序等待输入之前实际出现提示消息。
这是该计划的可观察行为。
答案 2 :(得分:0)
在C,C ++,Ada,Java,SML中,通过描述程序的(通常是许多可能的,不确定的)行为(暴露于I / O端口),没有明确的按条件规则。
distinct 规则的一个示例是说被零除会引发异常(Ada,Caml)或空取消引用会引发异常(Java)的示例。您可以更改规则以指定 else ,然后使用另一种语言(有些人宁愿称其为“方言”(*)。有一条不同的规则可以指定)某种编程语言的独特用法(例如独特的语法规则)涵盖了一些语法构造。
(*)据某些语言学家所说的方言是一种带有“军队”的语言。在这种情况下,这可能意味着一种没有委员会和专门的编译器编辑行业的编程语言。
假设规则不是唯一规则;它没有特别涵盖任何程序,甚至也不是可以以任何方式讨论,删除或更改的规则:所谓的“规则”只是重申了程序语义已定义,并且只能根据程序执行与“外部”世界的可见交互来可移植地(通用)定义。
外部世界可以是I / O接口(stdio),GUI,甚至是交互式解释器,它可以输出纯应用语言的结果值。在C和C ++中,包括(明确指定的)对易失性对象的访问,这是另一种说法,即必须严格按照ABI(应用程序二进制接口)在内存中表示给定点上的某些对象,而不必明确提及ABI。
什么是执行跟踪的定义,也称为“可见或可观察的行为”,它定义了“假设规则”的含义。即时规则尝试进行解释,但是这样做会使人们感到困惑,而不是澄清事情,因为它表达了作为附加语义规则的表达,为实现提供了更多的回旋余地。 >
摘要: