我使用了 Godbolt 的 CompilerExplorer。我想看看某些优化有多好。我的最小工作示例是:
#include <vector>
int foo() {
std::vector<int> v {1, 2, 3, 4, 5};
return v[4];
}
生成的汇编程序(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
正如我们所看到的, clang 知道答案,但在返回之前做了很多事情。在我看来,由于“operator new/delete”,甚至创建了向量。
谁能向我解释一下这里发生了什么以及为什么它不返回?
GCC 生成的代码(此处未复制)似乎显式构造了向量。有谁知道 GCC 无法推导出结果吗?
std::vector<T>
是一个相当复杂的类,涉及动态分配。尽管clang++
有时能够省略堆分配 https://godbolt.org/g/84bWMt,这是一个相当棘手的优化,您不应该依赖它。例子:
int foo() {
int* p = new int{5};
return *p;
}
foo(): # @foo()
mov eax, 5
ret
举个例子,使用std::array<T>
(不动态分配) 生成完全内联的代码 https://godbolt.org/g/8HHMTK:
#include <array>
int foo() {
std::array v{1, 2, 3, 4, 5};
return v[4];
}
foo(): # @foo()
mov eax, 5
ret
As 马克·格利斯 https://stackoverflow.com/users/1918193/marc-glisse在其他答案的评论中指出,这就是标准中所说的[expr.new] #10 http://eel.is/c++draft/expr.new#10:
允许实现省略对可替换全局分配函数([new.delete.single]、[new.delete.array])的调用。当这样做时,存储由实现提供或通过扩展另一个新表达式的分配来提供。如果未扩展分配,且满足以下条件,则实现可以扩展新表达式 e1 的分配,以为新表达式 e2 提供存储:[...]
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)