是和不是。
操作员+=
一般来说,移动语义不一定对operator+= 有帮助,因为您已经在修改左侧参数 (this),因此大多数时候您已经有资源可以使用。
不过,作为一种优化,它可能是值得的。想象一个std::string 实现,其默认构造函数不分配任何内存。然后std::string::operator+=(std::string&&) 可以简单地从 RHS 窃取资源。或者想象一下,RHS 缓冲区足够大,可以容纳所有内容,但 LHS 没有,那么如果您可以使用 RHS 缓冲区,那么您就是黄金:只需交换和前置即可。
所以,这可能是值得的,但你必须研究它。因此:
-
T& T::operator+=(T const&):一直在场
-
T& T::operator+=(T&&):在有意义时启用移动语义
运营商+
在这里它总是有用的(假设我们正在讨论移动语义对其有用的类)。
问题是,operator+ 会生成一个临时文件(出乎意料),因此它通常必须为这个临时文件创建资源。但是,如果它可以窃取它们而不是创建它们,那肯定会更便宜。
但是,您不需要提供所有重载:
T operator+(T const&, T const&)
T operator+(T&&, T const&)
T operator+(T const&, T&&)
-
T operator+(T&&, T&&)(消歧必填)
不,您可以重复使用 operator= 使用的相同技巧并在函数签名中创建临时权限(通过复制一个参数)。如果类型是可移动的,则将调用移动构造函数,否则它将是复制构造函数,但由于无论如何您都需要临时构造函数,因此不会损失性能。
inline T operator+(T left, T const& right) { left += right; return left; }
inline T operator+(T const& left, T right) { right += left; return right; } // commutative
inline T operator+(T left, T&& right) { left += right; return left; } // disambiguation
收益不大(3 而不是 4),但好吧,我会尽我所能!
当然,对于字符串,operator+ 不是可交换的(这就是为什么它是坏重载的原因),所以第二个重载的实际实现需要 prepend 方法。
编辑:关注Move semantics and operator overloading 似乎我有点过于热情了。从 Ben Voigt 的答案中窃取,我们得到:
inline T operator+(T left, T const& right) { left += right; return left; }
inline T operator+(const T& left, T&& right) { right += left; return right; }
另一方面,这似乎只适用于交换运算; - 不是这样工作的,但可能可以适应,另一方面,/ 和 %...