正如标题所说,
一个典型的答案是:
允许任何和所有代码转换不会改变程序的可观察行为的规则
我们会不时地从某些实现中获取行为,这些行为归因于此规则.好多次错了.那么,这个规则究竟是什么呢.标准没有明确地将此规则作为一个部分或段落提及,那么究竟什么属于这条规则的范围?对我来说,这似乎是一个灰色区域,标准没有详细定义.有人可以根据标准的参考资料详细说明细节.
注意:将其标记为C和C++,因为它与两种语言都相关.
考虑以下使用的简单代码new(我知道没有delete[],但它与此问题无关):
int main()
{
int* mem = new int[100];
return 0;
}
Run Code Online (Sandbox Code Playgroud)
是否允许编译器优化new呼叫?
在我的研究中,g ++(5.2.0)和Visual Studio 2015不会优化new呼叫,而clang(3.0+)则可以.所有测试都是在启用完全优化的情况下进行的(-O3用于g ++和clang,用于Visual Studio的发布模式).
是不是new在引擎盖下进行系统调用,使编译器无法(并且非法)优化它?
编辑:我现在已经从程序中排除了未定义的行为:
#include <new>
int main()
{
int* mem = new (std::nothrow) int[100];
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编辑2:
#include <new>
int main()
{
int* mem = new (std::nothrow) int[1000];
if (mem != 0)
return 1;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我玩过Godbolt的CompilerExplorer.我想看看某些优化是多么好.我的最低工作范例是:
#include <vector>
int foo() {
std::vector<int> v {1, 2, 3, 4, 5};
return v[4];
}
Run Code Online (Sandbox Code Playgroud)
生成的汇编程序(通过clang 5.0.0,-O2 -std = c ++ 14):
foo(): # @foo()
push rax
mov edi, 20
call operator new(unsigned long)
mov rdi, rax
call operator delete(void*)
mov eax, 5
pop rcx
ret
Run Code Online (Sandbox Code Playgroud)
可以看出,clang知道答案,但在返回之前会做很多事情.在我看来,即使是矢量也是由于"operator new/delete"而创建的.
任何人都可以向我解释这里发生了什么以及它为什么不回归?
GCC生成的代码(此处未复制)似乎明确构造了向量.有谁知道海湾合作委员会无法推断出结果?