虽然一元 operator+
是右结合的(就一元运算符而言),但二元 operator+
实际上是左结合的。
解决您的疑虑:
string d = a + b + c;
这首先将给出一个临时的结果(a+b)
。暂时无法解决,因为 a 和 b 无法更改。临时将在内存中保留至少a.size()+b.size()
字节,并将其内容a
复制b
到该新内存中。
然后c
将被添加到临时调用operator+(string&& lhs,const string& rhs)
中。这将获取临时文件并将其内容添加c
到其中,可能是在重新分配以补偿对更多空间的需求并将a.size()+b.size()
字节从旧内存复制到新内存之后。之后, 的内容c
将附加到新内存中的临时文件中。
然后移动构造函数将启动,获取临时内存的所有权。
总共最多给出两个(重新)分配(每个中一个operator+
),一个释放(在重新分配期间tmp + c
)和四个副本(a、b、c 和重新分配期间的临时)。没有复制操作,因为字符串内容可以整体复制(memcpy/memmove),因为char数组是不需要一个接一个复制的POD 。 a.size()+b.size()
这里唯一可以优化的是在执行时为最终结果临时保留足够的内存a+b
。虽然从语言/库的角度来看,对此无能为力,但优化器理论上可以看到分配和条件重新分配,并通过从一开始就保留足够的内存来做正确的事情。我不知道实现这种优化有多容易,但我想检测类似的东西string z = a + b + c + d + e + f...
并不容易,所以我不会指望它。
无论如何,临时变量通常不会损害您的程序性能,因为像这样的字符串操作很少发生在性能关键的地方。
如果您绝对必须提高该操作的性能,这是要走的路:
string d;
d.reserve(a.size() + b.size() + c.size());
d.append(a);
d.append(b);
d.append(c);
在储备调用期间导致一个分配,并且恰好是三个必要的副本。