为什么不把这个未使用的变量优化掉? [英] Why isn't this unused variable optimised away?
问题描述
#include< vector>
int foo(){
std :: vector< int> v {1,2,3,4,5};
return v [4];
}
生成的汇编器(由clang 5.0.0,-O2 -std = c
foo():#@foo()
push rax
mov edi ,20
调用operator new(unsigned long)
mov rdi,rax
调用operator delete(void *)
mov eax,5
pop rcx
ret
可以看出,clang知道答案,但在返回之前做了很多工作。在我看来,即使矢量是创建,因为运营商新/删除。
任何人都可以向我解释发生了什么,以及它为什么不只是返回?
由GCC生成的代码(未在此处复制)似乎明确构建了该向量。有人知道GCC不能推断出结果吗?
是一个相当复杂的类,涉及动态分配。虽然 clang ++
有时可以省略堆分配,这是一个相当棘手的优化,你不应该依赖它。例子: int foo(){
int * p = new int {5};
return * p;
$ / code>
foo():#@foo()
mov eax,5
ret
举例来说,使用 std :: array< T>
不会动态分配) 生成完整内联代码:
#include< array>
int foo(){
std :: array v {1,2,3,4,5};
return v [4];
$ / code>
foo():#@foo()
mov eax,5
ret
正如 Marc Glisse 所指出的在另一个答案的评论中,这是标准在 [expr.new]#10中所说的内容:
允许实现省略对可替换全局分配函数([new.delete.single])的调用, [new.delete.array])。当它这样做时,存储是由实现提供的,或者通过扩展另一个新表达式的分配来提供。这个实现可能会扩展新表达式e1的分配,以便为新表达式e2提供存储空间,如果以下情况属实,则分配不被扩展:[...]
I played around with Godbolt's CompilerExplorer. I wanted to see how good certain optimizations are. My minimum working example is:
#include <vector>
int foo() {
std::vector<int> v {1, 2, 3, 4, 5};
return v[4];
}
The generated assembler (by 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
As one can see, clang knows the answer, but does quite a lot of stuff before returning. It seems to my that even the vector is created, because of "operator new/delete".
Can anyone explain to me what happens here and why it does not just return?
The code generated by GCC (not copied here) seems to construct the vector explicitly. Does anyone know GCC is not capable to deduce the result?
std::vector<T>
is a fairly complicated class that involves dynamic allocation. While clang++
is sometimes able to elide heap allocations, it is a fairly tricky optimization and you should not rely on it. Example:
int foo() {
int* p = new int{5};
return *p;
}
foo(): # @foo() mov eax, 5 ret
As an example, using std::array<T>
(which does not dynamically allocate) 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
As Marc Glisse noted in the other answer's comments, this is what the Standard says in [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: [...]
这篇关于为什么不把这个未使用的变量优化掉?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!