“假设”规则到底是什么?


89

如标题所示,

“假设”规则到底是什么?

一个典型的答案是:

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

我们会不时地从某些实现中获得归因于该规则的行为。很多次是错误的。所以,这条规则到底是什么。该标准没有明确提及该规则的一部分或段落,那么该规则的作用范围到底是什么?对我来说,这似乎是一个灰色区域,该标准未对其进行详细定义。有人可以引用标准的参考文献来详细说明细节吗?

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


2
它指的是抽象机。
Alexey Frunze

将其同时标记为C和C ++,因为它与两种语言都相关”在任何语言中都具有相关性。
curiousguy

@AlexeyFrunze“ 指抽象机 ”指“抽象机”的状态是一种工具而不是终点,并且在合规性方面是不相关的,因为它不是规范工具,而是“抽象”。
curiousguy

Answers:


98

什么是“ 假设 ”规则?

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

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


标准在哪里引入此规则?

C ++ 11标准在第1.9 / 1节中引入了“ 假设 ”规则:

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

另外,一个解释性脚注增加了:

该规定有时被称为“假设”规则,因为只要可以根据可观察到的行为确定结果,就可以无视本国际标准的任何要求,而该实现可以自由地执行。该程序。例如,如果实际实现可以推断出未使用其值并且不会产生影响程序可观察行为的副作用,则无需评估表达式的一部分。


该规则究竟规定了什么?

第1.9 / 5段进一步规定:

执行格式正确的程序的合格实现应产生与具有相同程序和相同输入的抽象机相应实例的可能执行之一相同的可观察行为。但是,如果任何这样的执行包含未定义的操作,则此国际标准对使用该输入执行该程序的实现没有任何要求(甚至不涉及第一个未定义的操作之前的操作)。

值得强调的是,此约束仅在“执行格式正确的程序”时适用,并且执行包含未定义行为的程序的可能结果不受限制。第1.9 / 4段也对此做了明确规定:

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

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

符合标准的实现的最低要求是:

—严格根据抽象机的规则评估对易失对象的访问。

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

—交互式设备的输入和输出动态必须以这样的方式进行:在程序等待输入之前,实际上会发出提示输出。构成交互式设备的是实现定义的。

这些统称为程序的可观察行为。[ 注意:每种实现都可以定义抽象语义与实际语义之间更严格的对应关系。— 尾注 ]


在某些情况下该规则不适用吗?

据我所知,“ 按条件 ”规则的唯一例外是复制/移动省略符,即使类的复制构造函数,move构造函数或析构函数具有副作用,也可以使用该规则。确切的条件在第12.8 / 31段中指定:

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


2
我看到了这个引文。尚不清楚可观察到的行为的定义。可观察到的行为到底有什么资格?作为规则的例外,复制省略是众所周知的,实际上并不是我的问题的一部分。
Alok保存

2
@AlokSave:在C标准中,我们看到“访问易失性对象,修改对象,修改文件或调用执行任何这些操作的函数都是副作用”。大概在C ++标准中有等效的东西。非正式地说,我猜是“任何改变它与外界互动的东西”。
奥利弗·查尔斯沃思

1
改变抽象机状态的任何行为(例如,改变传入的变量或全局变量,或对I / O设备进行读写的行为)。
Mats Petersson

1
这是否意味着只要之后没有可观察的事件发生,删除一个无所事事的无限循环是不允许的?
哈罗德2013年

5
特别要注意的一点是,它仅适用于法律程序。任何调用未定义行为的行为都明确不在任何范围之内。
vonbrand 2013年

15

在C11中,该名称永远不会调用该规则。但是C就像C ++一样,用抽象机来定义行为。假设规则在C11 5.1.2.3p4和p6中

  1. 在抽象机中,所有表达式均按语义指定的方式求值。如果实际实现可以推断出未使用其值并且没有产生所需的副作用(包括由调用函数或访问易失性对象引起的副作用),则无需对表达式的一部分进行求值。

  2. [...]

  3. 符合标准的实现的最低要求是:

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

     

    这是程序的可观察行为。


-1

在C,C ++,Ada,Java,SML中,通过描述程序的(通常是许多可能的,不确定的)行为(暴露于I / O端口上的一系列交互)很好地指定的任何编程语言中,没有明确的假设规则

一个独特规则的示例是说被零除会引发异常(Ada,Caml)或空取消引用会引发异常(Java)的示例。您可以更改规则以指定其他内容,最终得到不同的语言(有些人宁愿称其为“方言”(*)。这里有一个独特的规则来指定编程语言的某些独特用法,例如独特的语言)。语法规则涵盖了一些语法构造。

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

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

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

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

摘要:

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

如果人们认为我错了,并且有一个独特的“好像规则”,为什么他们不尝试描述不带有“规则”的C ++(一种方言)变体?C ++规范甚至意味着什么?绝对不可能知道编译器是否符合要求。甚至定义符合性。
curiousguy
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.