gcc 为什么编译器不能优化std::string concat?

63lcw9qa  于 2023-10-19  发布在  其他
关注(0)|答案(1)|浏览(102)

我尝试了这样简单的代码:

#include <cstdio>
#include <string>

int main()
{
   const std::string s = std::string("a") + "b";
   puts(s.c_str());
   return 0;
 }

我希望编译器(gcc 4.8.2/clang 3.5.0)优化这样的代码,

int main()
 {
   puts("ab");
   return 0;
 }

但我不能得到这样的结果,我尝试不同的选项,如“-Ofast”,“-flto”,“-static-libstdc++",但总是看到反汇编输出三个函数调用:

...
callq  0x4017e0 <_ZNSsC2EPKcRKSaIcE>
... 
callq  0x401690 <_ZNSs6appendEPKc>
...
callq  0x401490 <_ZNSs4_Rep10_M_disposeERKSaIcE>

第一个是调用std::basic_string,std::allocator >::basic_string(char const*,std::allocator const&)。
任何编译器也是如此,它可以将这样的代码优化为puts(“ab”);或者至少是“std::string s(“ab”);“?
如果没有这样的编译器,是什么让这样的优化难以实现?

更新关于真实的世界用法。我在真实的代码中看到了很多这样的模式:

std::string s = std::string(string_const1) + string_const2 + string_variable + string_const3;

如果性能很重要,当然可以用更优化的方式重写这样的代码。
但是现代编译器在优化代码方面做得很好。例如,gcc有针对malloc/free/strcpy/strcat等的__内置函数。如果来自gcc的libstdc++的std::basic_string使用这些函数(malloc,free,strcpy,strcat)作为部分实现,为什么不预测函数使用的结果并给予答案呢?

pvcm50d1

pvcm50d11#

std::string涉及存储的动态分配,并且在大多数情况下,是一个极其复杂的实现,因此不能简化为编译时语义,无论编译器如何将常量折叠成精美的艺术。
但是:如果你的string实际上是这样声明的,为什么你一开始不使用char数组,而是选择string?如果你需要使用一些字符串来生成其他字符串,仍然有一些工具可以使用char数组来完成这项工作,特别是自从C11引入可变参数模板和constexpr以来。C的未来版本也有望引入std::string_literal来进一步简化这一点。

相关问题