我玩过 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”,甚至创建了 vector 。
谁能向我解释这里发生了什么以及为什么它不返回?
GCC 生成的代码(此处未复制)似乎明确地构造了 vector 。有谁知道 GCC 无法推断结果?
最佳答案
std::vector<T>
是一个相当复杂的类,涉及到动态分配。而clang++
is sometimes able to elide heap allocations ,这是一个相当棘手的优化,你不应该依赖它。示例:
int foo() {
int* p = new int{5};
return *p;
}
foo(): # @foo() mov eax, 5 ret
例如,使用 std::array<T>
(不动态分配) produces fully-inlined code :
#include <array>
int foo() {
std::array v{1, 2, 3, 4, 5};
return v[4];
}
foo(): # @foo() mov eax, 5 ret
作为 Marc Glisse在其他答案的评论中指出,这就是标准在 [expr.new] #10 中所说的:
An implementation is allowed to omit a call to a replaceable global allocation function ([new.delete.single], [new.delete.array]). When it does so, the storage is instead provided by the implementation or provided by extending the allocation of another new-expression. The implementation may extend the allocation of a new-expression e1 to provide storage for a new-expression e2 if the following would be true were the allocation not extended: [...]
关于c++ - 为什么这个未使用的变量没有被优化掉?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47072261/