2014-11-04 41 views
6

我尝试这样简单的代码:为什么编译器无法优化std :: string concat?

#include <cstdio> 
#include <string> 

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

我希望编译器(gcc 4.8.2/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> 

第一个是调用标准:: basic_string的, std :: allocator> :: basic_string(char const *,std :: allocator const &)。因此,任何编译器都可以优化这样的代码来放置(“ab”); 或至少到“std :: string s(”ab“);”?

如果没有这样的编译器,是什么使这种优化难以实现?

更新 关于真实世界的用法。 我看见/看到了这样的模式在实际代码中的许多地方:

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

如果性能很重要,当然有可能在更优化的方式重写 这样的代码。

但现代编译器做优秀的代码优化工作。 和gcc,例如malloc/free/strcpy/strcat等有__builtin函数。如果来自gcc的libstdC++的std :: basic_string使用它的这个函数(malloc,free,strcpy,strcat)作为实现的一部分,为什么不预测函数使用的结果并给出答案。

+0

因为C++类的构造函数和运算符都是函数,所以它们不是代数的,因此很难检测代数优化。 – didierc 2014-11-04 00:40:29

+1

你没有说你为什么要这样做,但会'const std :: string s =“a”“b”;'适合你的需求?字符串文字自动粘贴时,相邻书写。 – 2014-11-04 01:00:12

+0

要明确的是,C++标准允许程序被优化为'puts(“ab”);'或者等价的。但编译器不这样做。我想你不得不问一个编译器开发者,但也许它的一部分与尊重程序员的愿望有关。如果他们最终遵循* as-if *规则,那么会有很多投诉;例如进行系统调用以在屏幕上写入内容或者进行睡眠,根据C++ 14中的定义,没有可观察到的行为。 – 2014-11-04 04:33:24

回答

7

std::string涉及存储的动态分配,并且在大多数情况下是一个极其复杂的实现,因此不能简化为编译时语义,无论编译器如何不断地折叠成美术。

但是:如果您的string实际上是这样声明的,为什么您首先不使用char数组,但选择了string? 如果您需要使用一些字符串来生成其他字符,仍然有工具可以使用char数组来完成这项工作,特别是在C++ 11引入了可变参数模板和constexpr之后。未来的C++版本有望推出std::string_literal以进一步缓解这一问题。

+0

是否有可能使用C++ 14特性来获得一个constexpr std :: string :: operator +并实现OP的请求? – liori 2014-11-04 00:54:30

+0

@liori我应该这样认为,因为'string_literal'基于C++ 14。 – Columbo 2014-11-04 00:56:02

+1

还有一个复杂的问题,即GCC的'std :: string'仍然是写入时拷贝。 – 2014-11-04 01:03:15