问题标签 [as-if]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
3 回答
10435 浏览

c++ - “好像”规则到底是什么?

正如标题所说:

“好像”规则到底是什么?

一个典型的答案是:

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

有时,我们会不断从某些实现中获取行为,这些行为归因于该规则。很多时候都错了。

那么,这个规则究竟是什么?该标准没有明确将这条规则作为一个部分或段落提及,那么究竟什么属于该规则的范围?

对我来说,这似乎是一个标准没有详细定义的灰色区域。有人可以详细说明细节,引用标准中的参考资料吗?

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

0 投票
2 回答
228 浏览

c++ - C++ as-if 规则是否允许存储重新排序?

as-if ”规则基本上定义了允许实现在合法 C++ 程序上执行的转换。简而言之,所有不影响程序可观察行为的转换都是允许的。

至于“可观察行为”究竟代表什么,cppreference.com似乎与标准给出的定义不同,关于 input/output。我不确定这是对标准的重新解释,还是错误。

cppreference.com 的“ as-if ”规则:

  • 所有输入和输出操作都以相同的顺序和内容发生,就好像程序按照编写的方式执行一样。

标准的“ as-if ”规则:

  • 交互式设备的输入和输出动态应该以这样一种方式发生,即在程序等待输入之前实际交付提示输出。什么构成交互式设备是实现定义的

这种差异对我来说很重要,因为我想知道正常的商店重新排序是否是有效的编译器优化。根据 cppreference 的措辞,内存存储应该属于output operations它所提到的。但根据标准,内存存储似乎不是the output dynamics of interactive devices. (到底什么是交互式设备?)

一个可以效仿的例子。

现代编译器可能会为 function生成以下代码foo

如所见, store toA与 store to 一起重新排序B。它是否符合“ as-if ”规则?标准是否允许这种重新排序?

0 投票
4 回答
660 浏览

c++ - 评估 for 循环条件中的常量

在此示例中,将my_function(MY_CONSTANT)在每次迭代时进行评估,还是会自动存储?这是否取决于使用的优化标志?

0 投票
4 回答
4925 浏览

c++ - 执行时间为零的循环

是否有可能有一个执行时间为零的循环?我认为即使是一个空循环也应该有一个执行时间,因为它会产生开销。

0 投票
1 回答
99 浏览

c++ - 为什么不能消除无限循环?

这些规则涵盖了“as-if”规则:

对一致性实现的最低要求是:

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

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

  • 交互式设备的输入和输出动态应该以这样一种方式发生,即在程序等待输入之前实际交付提示输出。构成交互式设备的内容是实现定义的。

这些统称为程序的可观察行为。

...访问由 volatile glvalue (3.10) 指定的对象、修改对象、调用库 I/O 函数或调用执行任何这些操作的函数都是副作用,它们是状态的变化执行环境。...

但让我们采用如下程序:

事实是没有对象或对函数的调用,因此没有副作用,因此没有“执行环境状态的变化”。是什么阻止编译器将此代码编译为

这一切都是不确定的吗?无限循环本质上是“这是一个标签,一遍又一遍地跳到它”,并将一直持续到计算机关闭。代码没有做任何有趣的事情,没有计算,没有 I/O 输出等。

在内核代码中,无限循环变得有趣。但在用户空间代码中,无限循环通常是程序编写不佳的标志。那么我的逻辑有什么缺陷呢?

0 投票
1 回答
222 浏览

c++ - as-if 规则和删除分配

as-if 规则”赋予编译器优化或重新排序表达式的权利,这些表达式在某些规则下不会影响程序的输出和正确性,例如:

§1.9.5

执行格式良好的程序的一致实现应产生与具有相同程序和相同输入的抽象机的相应实例的可能执行之一相同的可观察行为。

我在上面链接的 cppreference url 特别提到了 C++14 下 volatile 对象的值以及“新表达式”的特殊规则:

New-expression 与 as-if 规则有另一个例外:即使提供了用户定义的替换并且具有可观察到的副作用,编译器也可能删除对可替换分配函数的调用。

我假设这里的“可替换”是例如在

§18.6.1.1.2

可替换:C++ 程序可以使用此函数签名定义一个函数,该函数签名替换 C++ 标准库定义的默认版本。

mem在 as-if 规则下可以删除或重新排序以下 内容是否正确?

有没有办法确保它不被删除,并保持在上下代码块之间?我想到了一个放置良好的 volatile (或者/或 volatile std::array 或 auto 的左侧),但是由于没有读取,我认为即使在as-if规则mem下也无济于事。

边注; 我根本无法让 Visual Studio 2015 优化mem和分配。

澄清:观察这一点的方法是对操作系统的分配调用来自两个块的任何 i/o。这样做的目的是针对测试用例和/或尝试在新位置分配对象。

0 投票
2 回答
150 浏览

c++ - 时间与“as-if”规则

关于一般的“as-if”规则有一个很大的问题,但我想知道在测量时间方面是否有任何例外。

考虑一下(取自此处稍作修改):

允许编译器应用任何产生相同结果的优化result。这里的重点是“as-if”规则并不直接适用于测量时间。当然,在应用优化时,测量的时间不应该是恒定的。

所以我的问题是:当根据“as-if”规则允许编译器将其重新排列为以下之一时,我怎么可能用上面的代码可靠地测量时间?

甚至“更优化”:

我假设没有理智的编译器会这样做,但是究竟是什么阻止了编译器进行这种“优化”呢?

TL;博士...

  • 可以观察优化代码和非优化代码之间的运行时差异
  • 如果允许编译器优化影响测量时间,是什么阻止编译器根本不为计时创建任何代码?
0 投票
2 回答
151 浏览

c++ - 为什么复制省略是 as-if 规则的一个例外?

为什么标准允许我的编译器应用复制省略,即使它涉及可见的副作用,从而打破了 as-if 规则?

当一个人保证复制省略时,这对我来说似乎是合理的,因为复制/移动的实际功能(这将引起程序行为中的可见变化)不一定存在,但是在 C+ 之前为什么/如何+17?

是不是因为编译器通常无法检测到副作用(我不知道这是否可能)?

0 投票
3 回答
677 浏览

c++ - 关于 C/C++ 标准中的时间/空间复杂度

最近我读到了关于抽象机器和 as-if 规则的东西(“as-if”规则到底是什么?),以及标准库对时间复杂度的要求(比如这个:Is list::size() 真的O(n)?)。

  1. 标准库的时间/空间复杂度要求是抽象机器还是真实的具体机器?

如果这些是在抽象机器方面,那么看起来一个实现实际上可以在复杂性方面生成效率较低的代码,即使它似乎不切实际。

  1. 标准是否提到了非标准库代码的时间/空间复杂性?

例如,我可能编写自定义排序代码并期望 O(n log n) 时间,但如果实现只是将其视为抽象机器中的代码,则允许在汇编和机器代码中生成较慢的排序,例如将其更改为 O (n^2) 排序,即使在实际情况下不太可能这样做。

或者我可能错过了抽象机器和真实具体机器之间的转换要求。你能帮我澄清一下吗?:)

虽然我主要是看C++标准的东西,但我也想知道C标准的情况。所以这个问题同时标记了两者。

0 投票
3 回答
605 浏览

c++ - cppreference中对轻松排序的解释是否错误?

cppreference.com上的文档中std::memory_order有一个轻松排序的示例:

轻松订购

标记memory_order_relaxed的原子操作不是同步操作;它们不会在并发内存访问之间强加顺序。它们只保证原子性和修改顺序的一致性。

例如,x 和 y 最初为零,

允许产生 r1 == r2 == 42,因为尽管 A在线程 1中排在B 之前,C 在线程 2 中排在 D之前,但没有什么可以阻止 D 在 y 的修改顺序中出现在 A 之前,而 B 从在 x 的修改顺序中出现在 C 之前。D 对 y 的副作用可能对线程 1 中的负载 A 可见,而 B 对 x 的副作用可能对线程 2 中的负载 C 可见。特别是,如果 D 在 C 中的 C 之前完成,则可能会发生这种情况线程 2,由于编译器重新排序或在运行时。

它说“C 在线程 2 中在 D 之前排序”。

根据排序前的定义,可以在评估顺序中找到,如果 A 在 B 之前排序,则 A 的评估将在 B 的评估开始之前完成。由于线程 2 中 C 在 D 之前排序,因此 C 必须在 D 开始之前完成,因此快照最后一句的条件部分将永远不会满足。