为什么允许 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): .
另一个问题讨论了优化器删除对 new
调用的合法性:
根据我的理解,允许编译器根据“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):