将右值引用作为左操作数重载加法操作符被认为是一种良好的做法

Is overloading the addition operator with an rvalue reference as its left hand operand considered as a good practice?

本文关键字:认为是 一种 操作符 引用 重载 操作数      更新时间:2023-10-16

假设str是一个用于存储字符串值的类,它将重载加法操作符以支持字符串连接。这样的:

str operator+(const str &a,const str &b);

但是问题是如果我们有这样的东西:

str s=str("Hel") + str("lo ") + str("Wor") + str("ld!");

然后它将创建3个临时对象(因为我们每次添加一个新对象),这些对象在此上下文中并不真正需要。此问题的一个简单解决方案可能是重载一个新的加法操作符,该操作符接受右值引用作为其左操作数,并在将该操作数与右操作数连接后,将该操作数也作为右值引用返回。像这样:

str &&operator+(str &&a,const str &b){
   a+=b;
   return std::move(a);
}

通过重载该操作符,上述语句将只创建一个临时对象,后续添加的操作将直接连接到该临时对象。

我的问题是,这种方法是解决这个问题的正确方法吗?

字符串通常可以被有效地移动。

因此,您的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

你可以写一个+来对称地处理左值和右值,但这是工作,讽刺的是,链式+把右值放在左边,因为链式+绑定它的参数的方式。

最后,您可以一直使用表达式模板,在赋值结果之前(几乎)什么都不做。这是有危险的,对于像玩具字符串类这样简单的东西来说是不值得的。如果您正在编写一个严肃的字符链类,那么在您完成了一系列其他改进之后,它可能是值得的。

相关文章: