对运算符+和/或运算符+ =使用移动语义有意义吗? [英] Does it make sense to use move semantics for operator+ and/or operator+=?

查看:125
本文介绍了对运算符+和/或运算符+ =使用移动语义有意义吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道在什么样的情况下,当重载operator +和/或operator + =时使用move语义是有意义的。即使在此问题中解释了如何执行此操作,但我无法将我的关于为什么我会这样做。让我们考虑operator + =。如果我只是通过引用右手边,并对左手边的对象进行适当的更改,则没有不必要的副本。所以我们回到同一点:在这种情况下,移动语义是否有益?

解决方案

p>

运算符+ =



移动语义不一定对运算符+ = 一般来说,因为你已经修改了左侧的参数( this ),所以你已经有资源使用大多数



仍然,作为优化,它可能是值得的。想象一个 std :: string 实现,其默认构造函数不分配任何内存。然后 std :: string :: operator + =(std :: string&&)< / code>可以简单地窃取来自RHS的资源。或者假设RHS缓冲区足够大以容纳所有内容,但是LHS不是,那么如果你可以使用RHS缓冲区,你就是黄金:只是交换和前缀。



所以,它可能值得,但你必须学习它。因此:




  • T :: operator + =(T const&):总存在




运算符+



这里总是有用的(假设我们在谈论移动语义有用的类)。



事情是, operator + 产生一个临时(蓝色),所以它通常必须创建资源这个临时的。



但是,你不需要提供所有的重载:




  • T operator +(T const& T const&)

  • T运算符+(T&& amp; T const&)

  • T运算符+

  • T运算符+(T&&&&& amp;) / li>


否,您可以重复使用 operator = 临时权限在函数签名中(通过复制一个参数)。如果类型是可移动的,移动构造函数将被调用,否则它将是复制构造函数,但是因为你需要临时的,而不会失去性能。

  inline T operator +(T left,T const& right){left + = right; return left; } 
inline T operator +(T const& left,T right){right + = left;返回右} // commutative
inline T operator +(T left,T&& right){left + = right; return left; } // disambiguation

没有多少增益(3而不是4)



当然,对于字符串, operator + 不是可交换的(这就是为什么它是一个坏的重载),因此第二个重载的实际实现将需要 prepend 方法。



:按照移动语义和运算符重载,似乎我有点过度热情。从Ben Voigt的回答窃取,我们得到:

  inline T operator +(T left,T const& right){left + = right ; return left; } 
inline T operator +(const T& left,T&& right){right + = left;返回右}

另一方面,这似乎只适用于交换操作; - 不工作,但可以修改, / 另一方面...


I was wondering in what kind of cases it makes sense to use move semantics when overloading operator+ and/or operator+=. Even though it is explained in this question how one could do this, I can't wrap my head around as to why I'd do it. Let's consider operator+=. If I just pass right hand side by reference and make the appropriate changes on the left hand side object, there are no unnecessary copies anyway. So we come back to the same point: Would move semantics be beneficial in such a case?

解决方案

Yes and no.

operator+=

Move semantics are not necessarily helpful for operator+= in general, because you are already modifying the left hand side argument (this), so you already have resources to work with most of the times.

Still, as an optimization, it might be worth it. Imagine a std::string implementation whose default constructor does not allocate any memory. Then std::string::operator+=(std::string&&) could simply steal the resources from RHS. Or imagine that the RHS buffer is big enough to hold everything but the LHS is not, then if you can use the RHS buffer you're golden: just swap and prepend.

So, it may be worth it, but you have to study it. Therefore:

  • T& T::operator+=(T const&): always present
  • T& T::operator+=(T&&): to enable move semantics when it makes sense

operator+

Here it is always useful (providing we are talking about classes for which move semantics are useful).

The thing is, operator+ produces a temporary (out of the blue) so it generally has to create resources for this temporary. However if it can steal them rather than create them, it's certainly cheaper.

However, you need not provide all overloads:

  • T operator+(T const&, T const&)
  • T operator+(T&&, T const&)
  • T operator+(T const&, T&&)
  • T operator+(T&&, T&&) (required for disambiguation)

No, you can reuse the same trick that operator= use and create the temporary right in the function signature (by taking one argument by copy). If the type is movable, the move constructor will get called, otherwise it'll be the copy constructor, but since you need the temporary anyway, no loss of performance.

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

Not much of a gain (3 instead of 4) but well, I'll take what I can!

Of course, for string, operator+ is not commutative (which is why it is a bad overload), so the actual implementation of the second overload would require a prepend method.

EDIT: following Move semantics and operator overloading it seems that I was a bit over-enthusiastic. Stealing from Ben Voigt's answer, we get:

inline T operator+(T left, T const& right) { left += right; return left; }
inline T operator+(const T& left, T&& right) { right += left; return right; }

On the other hand, this seems to only work for commutative operations; - does not work that way but can probably be adapted, / and % on the other hand...

这篇关于对运算符+和/或运算符+ =使用移动语义有意义吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆