为什么这个未使用的变量没有被优化掉?

2024-05-12

我使用了 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(使用前将#替换为@)

为什么这个未使用的变量没有被优化掉? 的相关文章

随机推荐