我不会担心的。如果您在循环中执行此操作,字符串将始终预先分配内存以最小化重新分配 - 在这种情况下只需使用 operator+=。如果你手动做,像这样或更长的时间
a + " : " + c
然后它会创建临时对象——即使编译器可以消除一些返回值副本。这是因为在连续调用的operator+ 中,它不知道引用参数是引用命名对象还是从子operator+ 调用返回的临时对象。在没有先进行分析之前,我宁愿不担心它。但是,让我们举一个例子来说明这一点。我们首先引入括号以使绑定清晰。为了清楚起见,我将参数直接放在函数声明之后。在此之下,我展示了结果表达式是什么:
((a + " : ") + c)
calls string operator+(string const&, char const*)(a, " : ")
=> (tmp1 + c)
现在,除此之外,tmp1 是第一次使用显示的参数调用 operator+ 返回的内容。我们假设编译器非常聪明并且优化了返回值副本。所以我们最终得到一个包含a 和" : " 连接的新字符串。现在,这发生了:
(tmp1 + c)
calls string operator+(string const&, string const&)(tmp1, c)
=> tmp2 == <end result>
将其与以下内容进行比较:
std::string f = "hello";
(f + c)
calls string operator+(string const&, string const&)(f, c)
=> tmp1 == <end result>
它对临时字符串和命名字符串使用相同的函数!因此编译器必须将参数复制到一个新字符串中并附加到该字符串并从operator+ 的正文中返回它。它不能占用临时内存并附加到该内存。表达式越大,必须完成的字符串副本就越多。
Next Visual Studio 和 GCC 将支持 c++1x 的 移动语义(补充 复制语义)和右值引用作为实验性添加。这允许确定参数是否引用临时参数。这将使这样的添加速度惊人地快,因为以上所有内容都将在一个没有副本的“添加管道”中结束。
如果结果是瓶颈,你仍然可以这样做
std::string(a).append(" : ").append(c) ...
append 调用将参数附加到*this,然后返回对其自身的引用。所以没有复制临时文件。或者,可以使用operator+=,但您需要丑陋的括号来确定优先级。