假设str
是一个用于存储字符串值的类,它会使加法运算符重载以支持字符串连接。像这样:
str operator+(const str &a,const str &b);
但问题是如果我们有这样的事情:
str s=str("Hel") + str("lo ") + str("Wor") + str("ld!");
然后它会创建3个临时对象(因为我们在每次添加时都会得到一个新对象),在这种情况下并不需要它们。 这个问题的一个简单解决方案可能是重载一个新的加法运算符,该运算符接受一个rvalue-reference作为其左操作数,并在将该操作数与右操作数连接后将其返回为rvalue-reference。像这样:
str &&operator+(str &&a,const str &b){
a+=b;
return std::move(a);
}
通过重载此运算符,然后提到的语句只会创建一个临时对象,而后续添加只会连接到该临时对象。
我的问题是,这种方法是否是解决此问题的正确方法?
答案 0 :(得分:5)
通常可以有效地移动字符串。
因此,您的operator+
应该返回str
而不是str&&
。这意味着
str const& bob = str1 + str2;
没有可怕的破坏,或更合理地打破:
for(char c : str1 + str2)
并没有可怕的破裂。
其次,只需按值str
。如果它是一个右值,它会被移入(便宜)。如果它是左值,它将被复制(然后扩展,然后返回)。还便宜。
str operator+( str lhs, str const& rhs )
最后,你可以让rhs成为任何可转换为str
(或有效添加到str
)的模板类型,以删除可能无用的转换。
特别是
str a = str("Hello") + " world";
应构建"Hello"
,然后附加" world"
而不构建另一个str
对象,然后将该结果移至a
。
你可以编写一个+
来左右对称地处理rvalues,但这是有效的,具有讽刺意味的是,链接+
将rvalues放在左边,因为链接{{1}绑定它的论点。
最后,您可以一直使用表达式模板,并且在分配结果之前几乎不做任何事情。这有危险,并且对于像玩具串类这样简单的东西是不值得的。如果您正在编写一个严肃的字符串类,那么在您完成其他一些改进之后可能是值得的。