什么是“如果”规则?

正如标题所说,

什么是“如果”规则?

一个典型的答案是:

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

我们不时地从一些归因于这个规则的实现中获得行为。 错误地多次。 那么,这个规则到底是什么? 标准没有明确提及这条规则作为一个部分或段落,那么究竟是什么属于这个规则的范围? 对我来说,这似乎是一个灰色的地方,没有标准的详细定义。 有人可以详细说明引用标准的参考资料。

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

什么是“ 假设 ”规则?

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

只要程序的行为与抽象机器的C ++标准所规定的语义保持一致,就可以让执行自由地执行优化。


标准在哪里介绍这个规则?

C ++ 11标准在1.9 / 1中引入了“ 如果 ”规则:

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

另外,解释性脚注还说:

这个规定有时被称为“假设”规则 ,因为一个实现可以自由地忽视这个国际标准的任何要求,只要结果就好像该要求已经被遵守一样,就可以从可观察到的行为的程序。 例如,一个实际的实现不需要评估一个expression式的一部分,如果它可以推断出它的值没有被使用,并且没有产生影响该程序的可观察行为的副作用。


这个规则是什么规定的?

第1.9 / 5款进一步规定:

执行一个格式良好的程序的一致性实现应该产生与具有相同程序和相同input的抽象机器的相应实例的可能执行之一相同的可观察行为 。 但是,如果任何这样的执行包含未定义的操作,则本国际标准不要求执行该程序的实现(即使在第一个未定义的操作之前的操作)。

值得强调的是,这种约束只适用于“执行格式良好的程序” ,而执行含有未定义行为的程序的可能结果是不受约束的。 第1.9 / 4段也明确指出了这一点:

本标准中某些其他操作未定义(例如,试图修改const对象的效果)。 [注: 本标准对含有未定义行为的程序行为没有要求 。 – 注意]

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

符合实现的最低要求是:

– 访问易失性对象严格按照抽象机器的规则进行评估。

– 在程序终止时,写入文件的所有数据应与根据抽象语义执行程序所产生的结果相同。

– 交互设备的input和输出dynamic应该以这样一种方式进行,即在程序等待input之前实际提供提示输出。 什么构成交互设备是由实现定义的。

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


有没有这个规则不适用的情况?

就我所知,唯一的例外是“复制/移动省略”,尽pipe复制构造函数,移动构造函数或类的析构函数具有副作用,但它仍然是允许的。 第12.8 / 31条规定了确切的条件:

当满足某些标准时, 即使为复制/移动操作select的构造函数和/或对象的析构函数具有副作用允许实现省略类对象的复制/移动构造。 […]

在C11中,这个规则永远不会被这个名字所调用。 不过,就像C ++一样,C定义了抽象机器的行为。 as if规则在C11 5.1.2.3p6中 :

  1. 符合实现的最低要求是:

    • volatile对象的访问严格按照抽象机器的规则进行评估。
    • 在程序结束时,写入文件的所有数据应该与根据抽象语义执行程序所产生的结果相同。
    • 交互设备的input和输出dynamic应按照7.21.3的规定进行。 这些要求的意图是尽可能快地出现无缓冲或线路缓冲的输出,以确保提示消息实际上出现在等待input的程序之前。

    这是该程序的可观察行为。