我尝试了这样简单的代码:
#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)作为部分实现,为什么不预测函数使用的结果并给予答案呢?
1条答案
按热度按时间pvcm50d11#
std::string
涉及存储的动态分配,并且在大多数情况下,是一个极其复杂的实现,因此不能简化为编译时语义,无论编译器如何将常量折叠成精美的艺术。但是:如果你的
string
实际上是这样声明的,为什么你一开始不使用char
数组,而是选择string
?如果你需要使用一些字符串来生成其他字符串,仍然有一些工具可以使用char
数组来完成这项工作,特别是自从C11引入可变参数模板和constexpr
以来。C的未来版本也有望引入std::string_literal
来进一步简化这一点。