c++ - 对 operator+ 和/或 operator+= 使用 move 语义有意义吗?

标签 c++ c++11 operator-overloading move

我想知道在什么情况下在重载 operator+ 和/或 operator+= 时使用 move 语义是有意义的。尽管在 this question 中有解释怎么能做到这一点,我想不通为什么要这样做。让我们考虑运算符+=。如果我只是通过引用传递右侧并在左侧对象上进行适当的更改,则无论如何都没有不必要的拷贝。所以我们回到同一点:在这种情况下 move 语义是否有益?

最佳答案

是也不是。

运算符+=

一般来说, move 语义不一定对 operator+= 有帮助,因为您已经在修改左侧参数 (this),所以您已经有工作资源大多数时候。

不过,作为一种优化,它可能是值得的。想象一个 std::string 实现,其默认构造函数不分配任何内存。然后 std::string::operator+=(std::string&&) 可以简单地从 RHS 窃取资源。或者想象一下,RHS 缓冲区大到足以容纳所有内容,但 LHS 不行,那么如果您可以使用 RHS 缓冲区,那您就大功告成了:只需交换并添加前缀即可。

所以,这可能是值得的,但你必须研究它。因此:

  • T& T::operator+=(T const&):始终存在
  • T& T::operator+=(T&&):在有意义时启用 move 语义

运营商+

在这里它总是有用的(前提是我们讨论的是 move 语义对其有用的类)。

问题是,operator+ 生成了一个临时文件(出乎意料),因此它通常必须为这个临时文件创建资源。但是,如果它可以窃取它们而不是创建它们,那肯定会更便宜。

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

  • T 运算符+(T const&, T const&)
  • T运算符+(T&&, T const&)
  • T 运算符+(T const&, T&&)
  • T operator+(T&&, T&&)(消歧需要)

不,您可以重用 operator= 使用的相同技巧,并在函数签名中创建临时权限(通过复制一个参数)。如果类型是可 move 的,将调用 move 构造函数,否则它将是复制构造函数,但由于无论如何你都需要临时的,所以不会损失性能。

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; }

另一方面,这似乎只适用于交换操作; - 不是这样工作的,但可能可以进行调整,另一方面,/%...

关于c++ - 对 operator+ 和/或 operator+= 使用 move 语义有意义吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9851188/

相关文章:

c++ - g++ libstdc++.so.6 : version `CXXABI_1.3.9' not found after upgrade to gcc version 7. 3.0 从 4.8.5

C++ 将文本文件创建/解析为函数

c++ - 如何访问Boost Graph中的边信息?

c++ - 数值 vector 运算符重载+右值引用参数

c++ - 为什么断点会在 .h 文件中跳转?

c++ - 为什么人们使用原子交换而不是存储?

c++ - 在 C++11 STL 之前模拟大括号列表初始化

c++ - 在类的方法中初始化类的对象成员

c++ - 了解 C++ 中的运算符重载

c++ - 为数学函数 C++ 实现乘法运算符