提问人:Alok Save 提问时间:3/30/2013 最后编辑:Remy LebeauAlok Save 更新时间:2/12/2021 访问量:12899
究竟什么是“假设”规则?
What exactly is the "as-if" rule?
问:
正如标题所说:
一个典型的答案是:
允许不更改程序的可观察行为的任何和所有代码转换的规则
有时,我们会不断从某些实现中获得行为,这些行为归因于此规则。很多次都错了。
那么,这条规则到底是什么呢?该标准没有明确提及该规则作为章节或段落,那么该规则究竟属于该规则的范畴范围是什么?
对我来说,这似乎是一个灰色地带,标准没有详细定义。有人可以引用标准中的参考资料详细说明细节吗?
注意:将其标记为 C 和 C++,因为它与这两种语言相关。
答:
什么是“假设”规则?
“假设”规则基本上定义了允许实现在合法的 C++ 程序上执行哪些转换。简而言之,所有不影响程序的“可观察行为”的转换(有关精确定义,请参见下文)都是允许的。
目标是让实现可以自由地执行优化,只要程序的行为符合抽象机器的 C++ 标准指定的语义。
该标准在哪里引入了此规则?
C++11 标准在第 1.9/1 段中引入了“假设”规则:
本国际标准中的语义描述定义了一个参数化的非确定性抽象 机器。本国际标准对符合要求的实施结构没有要求。 特别是,它们不需要复制或模仿抽象机器的结构。相反,顺从是 实现需要模拟(仅)抽象机器的可观察行为,如所述 下面。
此外,解释性脚注还添加了:
这一规定有时被称为“假设”规则,因为实现可以自由地无视任何要求 国际标准,只要结果是好像已经遵守了要求,只要可以从中确定 程序的可观察行为。例如,如果可以的话,实际实现不需要计算表达式的一部分 推断其值未被使用,并且不会产生影响程序可观察行为的副作用。
该规则究竟要求什么?
第1.9/5段进一步规定:
执行格式良好的程序的符合要求的实现应产生相同的可观察行为 作为具有相同程序的抽象机器的相应实例的可能执行之一 和相同的输入。但是,如果任何此类执行包含未定义的操作,则此国际 标准对使用该输入执行该程序的实现没有要求(甚至没有 关于第一个未定义操作之前的操作)。
值得强调的是,此约束仅适用于“执行格式良好的程序”,并且执行包含未定义行为的程序的可能结果是不受约束的。第1.9/4段也明确指出了这一点:
某些其他操作在本国际标准中被描述为未定义(例如,效果 尝试修改 const 对象)。[ 注:本国际标准对 包含未定义行为的程序的行为。——尾注]
最后,关于“可观察行为”的定义,第1.9/8段如下:
对符合要求的实现的最低要求是:
— 对易失性对象的访问严格按照抽象机器的规则进行评估。
— 在程序终止时,写入文件的所有数据应与以下可能的结果之一相同: 根据抽象语义执行程序会产生。
— 交互式设备的输入和输出动态应以提示 输出实际上是在程序等待输入之前传递的。什么是交互式设备 是实现定义的。
这些统称为程序的可观察行为。[ 注:更严格 抽象语义和实际语义之间的对应关系可以由每个实现定义。—完 注意 ]
在哪些情况下,此规则不适用?
据我所知,“假设”规则的唯一例外是复制/移动省略,即使类的复制构造函数、移动构造函数或析构函数有副作用,也是允许的。第12.8/31段规定了具体条件:
当满足某些条件时,允许实现省略类的复制/移动构造 对象,即使为复制/移动操作选择的构造函数和/或为对象选择的析构函数也是如此 有副作用。[...]
评论
在 C11 中,从不使用该名称调用规则。然而,C就像C++一样,用抽象机器来定义行为。as-if 规则位于 C11 5.1.2.3p4 和 p6 中:
在抽象机器中,所有表达式都按照语义指定进行计算。如果实际实现可以推断出表达式的值未被使用,并且不会产生所需的副作用(包括由调用函数或访问可变对象引起的任何副作用),则无需计算表达式的一部分。
[...]
对符合要求的实现的最低要求是:
- 对对象的访问严格按照抽象机器的规则进行评估。
volatile
- 在程序终止时,写入文件的所有数据应与根据抽象语义执行程序所产生的结果相同。
- 交互设备的输入和输出动态应采取 地点,如 7.21.3 中指定。这些要求的目的是尽快出现无缓冲或行缓冲的输出,以确保提示消息在程序等待输入之前实际出现。
这是程序的可观察行为。
在 C、C++、Ada、Java、SML 中...在任何通过描述程序(通常许多可能的、非确定性的)行为(暴露于 I/O 端口上的一系列交互)来明确指定的编程语言中,没有明确的 as-if 规则。
不同规则的一个例子是,除以零会引发异常(Ada、Caml)或空取消引用会引发异常(Java)。您可以更改规则以指定其他内容,最终会得到一种不同的语言(有些人宁愿称之为“方言”(*)。一个不同的规则可以指定编程语言的一些不同用法,就像不同的语法规则涵盖一些语法结构一样。
(*)根据一些语言学家的说法,方言是一种带有“军队”的语言。在这种情况下,这可能意味着一种没有委员会的编程语言和特定的编译器编辑器行业。
仿佛规则不是一个单独的规则;它没有特别涵盖任何程序,甚至不是一个可以以任何方式讨论、删除或更改的规则:所谓的“规则”只是重申程序语义是定义的,并且只能根据程序执行与“外部”世界的可见交互进行可移植(普遍)定义。
外部世界可以是 I/O 接口 (stdio)、GUI,甚至是输出纯应用语言结果值的交互式解释器。在 C 和 C++ 中,包括对易失性对象的(模糊指定的)访问,这是另一种说法,即给定点的某些对象必须严格按照 ABI(应用程序二进制接口)在内存中表示,而无需显式提及 ABI。
什么是执行跟踪的定义,也称为可见或可观察行为,定义了“假设规则”的含义。as-if 规则试图解释它,但这样做,它让人们感到困惑多于澄清事情,因为它表达了作为附加语义规则的表达,为实现提供了更多的回旋余地。
总结:
- 所谓的“假设规则”并没有放松对实现的任何限制。
- 您不能删除任何编程语言中根据可见行为(为与外部世界交互而编写的执行跟踪)指定的 as-if 规则来获取不同的方言。
- 不能将 as-if 规则添加到任何未在可见行为方面指定的编程语言。
评论