Vem*_*ulo 7 c++ static-constructor compiler-optimization
如果我使用 GCC 或 Clang 编译此代码并启用-O2优化,我仍然会得到一些全局对象初始化。任何代码是否有可能访问这些变量?
#include <string>
static const std::string s = "";
int main() { return 0; }
Run Code Online (Sandbox Code Playgroud)
编译器输出:
main:
xor eax, eax
ret
_GLOBAL__sub_I_main:
mov edx, OFFSET FLAT:__dso_handle
mov esi, OFFSET FLAT:s
mov edi, OFFSET FLAT:_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev
mov QWORD PTR s[rip], OFFSET FLAT:s+16
mov QWORD PTR s[rip+8], 0
mov BYTE PTR s[rip+16], 0
jmp __cxa_atexit
Run Code Online (Sandbox Code Playgroud)
具体来说,我没想到这个_GLOBAL__sub_I_main:部分。
编辑:即使使用简单的自定义类型,编译器仍然会生成一些代码。
class Aloha
{
public:
Aloha () : i(1) {}
~Aloha() = default;
private:
int i;
};
static const Aloha a;
int main() { return 0; }
Run Code Online (Sandbox Code Playgroud)
编译器输出:
main:
xor eax, eax
ret
_GLOBAL__sub_I_main:
ret
Run Code Online (Sandbox Code Playgroud)
使用短字符串优化 (SSO) 编译该代码可能相当于获取 的std::string成员变量的地址。构造函数必须在编译时分析字符串长度,并选择它是否适合std::string对象的内部存储,或者必须动态分配内存,但随后发现它从未被读取,因此可以优化分配代码。
在这种情况下,缺乏优化可能是一种优化缺陷,仅限于像这样的简单外围示例:
const int i = 3;
int main()
{
return (long long)(&i); // to make sure that address was used
}
Run Code Online (Sandbox Code Playgroud)
GCC生成代码:
i:
.long 3 ; this a variable
main:
push rbp
mov rbp, rsp
mov eax, OFFSET FLAT:i
pop rbp
ret
Run Code Online (Sandbox Code Playgroud)
GCC 也不会优化这段代码:
const int i = 3;
const int *p = &i;
int main() { return 0; }
Run Code Online (Sandbox Code Playgroud)
在文件作用域中声明的静态变量,尤其是 const 限定的变量,可以根据 as-if 规则进行优化,除非 使用了它们的地址,GCC 只对 const 限定的变量执行此操作,无论用例如何。获取变量的地址是一种可观察的行为,因为它可以传递到某个地方。追踪的逻辑太复杂而难以实现,并且没有什么实际价值。
当然,不使用地址的代码
const int i = 3;
int main() { return i; }
Run Code Online (Sandbox Code Playgroud)
优化保留存储的结果:
main:
mov eax, 3
ret
Run Code Online (Sandbox Code Playgroud)
从 C++20 constexpr 构造std::string? 根据旧规则,如果结果依赖于参数,则它不能是编译时表达式。std::string如果字符串太长,可能会动态分配内存,这不是编译时操作。看来,在某些情况下,目前唯一支持 C++20 所需功能的主流编译器是 MSVC。
| 归档时间: |
|
| 查看次数: |
751 次 |
| 最近记录: |