"仿佛规则"赋予编译器权利,在特定规则下可以优化掉或重新排序不影响程序输出和正确性的表达式。其中,§1.9.5规定符合要求的实现执行良好形式的程序时,应该生成与相同程序和输入在抽象机的对应实例中可能执行的相同观察行为。我上面提供的cppreference网址特别提到了C++14下易失性对象值的特殊规则,以及“new expressions”的规则:
有没有一种方法可以确保它不被移除,并留在上下代码块之间?一个放置得当的 volatile(或者是 volatile std::array 或者是 auto 左侧)会让人想起,但是由于没有读取 mem,我认为即使在 as-if 规则下也无济于事。
顺便说一下;我一直无法让 Visual Studio 2015 优化掉 mem 和分配。
澄清一下:观察这个的方法是,在两个代码块之间的任何 i/o 之间调用操作系统进行分配。这样做的目的是为了测试用例和/或尝试让对象分配到新位置。
我认为这里所说的“可替换”是指例如在...中讨论的内容。new-expression有另一个例外,即使提供了具有可观测副作用的用户定义替换,编译器也可以删除对可替换分配函数的调用。
§18.6.1.1.2
可替换的:C++程序可以定义一个带有此函数签名的函数,以代替C++标准库定义的默认版本。
根据as-if规则,下面的mem
是否可以被删除或重新排序?
{
... some conformant code // upper block of code
auto mem = std::make_unique<std::array<double, 5000000>>();
... more conformant code, not using mem // lower block of code
}
有没有一种方法可以确保它不被移除,并留在上下代码块之间?一个放置得当的 volatile(或者是 volatile std::array 或者是 auto 左侧)会让人想起,但是由于没有读取 mem,我认为即使在 as-if 规则下也无济于事。
顺便说一下;我一直无法让 Visual Studio 2015 优化掉 mem 和分配。
澄清一下:观察这个的方法是,在两个代码块之间的任何 i/o 之间调用操作系统进行分配。这样做的目的是为了测试用例和/或尝试让对象分配到新位置。
make_unique
创建了一个新对象,据我所知,C++编译器不会因为副作用的可能性而优化掉对象的创建。它们可能省略不必要的构造函数调用,但始终确保至少调用一次构造函数。否则,具有具有副作用的构造函数的RAII对象的代码将无法安全地依赖于该模式,除非包含内存屏障。 - JABvolatile
到底有多远:new volatile int(10)
。规范说明访问易失性变量是可观察的副作用,而不是调用分配函数。因此,如果编译器安排在其他地方分配内存,则仍然可以省略对分配函数的调用!?只是根据那个 cppreference 引用..我还没有查找相关规范。 - Johannes Schaub - litb