自GCC 5.1起优化器是否失效?std::string.size()常量传播异常
GCC中std::string.size()常量传播的变化不是Bug
这不是编译器Bug,而是C++标准演进和GCC默认编译标准版本变化共同导致的行为差异:
GCC默认标准版本的变化:GCC 5.1默认使用C11标准,而GCC 11及之后的版本(包括13.2)默认切换为C17标准。不同标准对
std::string的编译期优化支持程度不同。C++17及之前的限制:在C20之前,
std::string的构造函数并非constexpr,标准没有明确允许编译器将字符串字面量构造std::string并调用size()的操作视为编译期常量。GCC 5.1的激进优化属于非标准的拓展行为,后续版本为了严格遵循C17标准,调整了优化策略,所以会生成实际构造、销毁std::string的汇编代码(即使最终返回值是确定的1)。C++20的优化支持:C++20标准扩展了
constexpr std::string的能力,明确允许在编译期完成字符串对象的构造和size()等成员函数的调用。当指定-std=c++20编译时,GCC可以合法地进行常量传播,直接将std::string("a").size()计算为编译期常量1,生成极简的汇编代码。
代码示例与汇编对比
原测试代码:
#include <string> int main() { return std::string("a").size(); }
GCC 5.1 -O3(默认C++11)汇编:
main: mov eax, 1 ret
GCC 13.2 -O3(默认C++17)汇编:
main: sub rsp, 40 lea rax, [rsp+16] mov rdi, rsp mov QWORD PTR [rsp+8], 1 mov QWORD PTR [rsp], rax mov eax, 97 mov WORD PTR [rsp+16], ax call std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_dispose() mov eax, 1 add rsp, 40 ret
GCC 13.2 -O3 -std=c++20汇编会回到极简版本,和GCC 5.1的输出一致。
内容的提问来源于stack exchange,提问作者Sergey Kolesnik
相关产品推荐
相关产品推荐

