为什么允许 C++ 编译器优化带有副作用的内存分配?

Why is it allowed for the C++ compiler to opmimize out memory allocations with side effects?

另一个问题讨论了优化器删除对 new 调用的合法性:. I have read the question, the answers, and N3664

根据我的理解,允许编译器根据“as-if”规则删除或合并动态分配,即如果生成的程序的行为就好像没有进行任何更改,相对于定义在标准。

我测试了使用 clang++ 和 g++ 编译以下双文件程序,以及 -O1 优化,但我不明白如何允许删除分配。

// main.cpp
#include <cstdio>

extern int g_alloc;

static int* foo(int n)
{
  // operator new is globally overridden in the other file.
  return new int(n);
}

int main(int argc, char** argv)
{
  foo(argc);
  foo(argc*2);
  printf("allocated: %d\n", g_alloc);
  return g_alloc;
}
// new.cpp
#include <cstdio>
#include <cstdlib>
#include <new>

int g_alloc = 0;

void* operator new(size_t n)
{
  g_alloc += n;
  printf("new %lu\n", n);
  return malloc(n);
}

想法是用一个有副作用的函数覆盖默认值 operator new(size_t):打印一条消息并修改一个全局变量,后者用作退出代码。

副作用不会影响分配本身,但它仍然会改变程序的输出。事实上,在没有优化的情况下编译时,输出是:

new 4
new 4
allocated: 8

但是一旦启用优化,输出就是:

allocated: 0

结果与使用标准 98 到 17 时的结果相同。

编译器如何允许省略此处的分配?它如何符合假设规则?

Allocation elision is an optimization that is outside of and in addition to the as-if rule. Another optimization with the same properties is copy elision (not to be confused with mandatory elision, since C++17): .