c++ - 使用哪个 : move assignment operator vs copy assignment operator

标签 c++ c++11 overload-resolution

我似乎不明白为什么要使用移动赋值运算符:

CLASSA & operator=(CLASSA && other); //move assignment operator

结束了,复制赋值运算符:

CLASSA & operator=(CLASSA  other); //copy assignment operator

移动赋值运算符仅采用r值引用,例如

CLASSA a1, a2, a3;
a1 = a2 + a3;

复制赋值运算符中,other可以是使用复制构造函数移动构造函数的构造函数(如果 other 是用右值初始化的,它可以是移动构造的——如果 move-constructor 定义了——)。

如果它是copy-constructed,我们将进行 1 次复制,并且无法避免该复制。

如果它是move-constructed,那么性能/行为与第一个重载产生的相同。

我的问题是:

1- 为什么要实现移动赋值运算符

2- 如果other 是从右值构造的,那么编译器会选择调用哪个赋值运算符?为什么?

最佳答案

你不是在比较同类

如果您正在编写像 std::unique_ptr 这样的只能移动的类型,那么移动赋值运算符将是您唯一的选择。

更典型的情况是你有一个可复制的类型,在这种情况下我认为你有三个选择。

  1. T& operator=(T const&)
  2. T& operator=(T const&)T& operator=(T&&)
  3. T& operator=(T) 并移动

请注意,在一个类中同时使用您建议的重载不是一种选择,因为它会产生歧义。

选项 1 是传统的 C++98 选项,在大多数情况下都能正常运行。但是,如果您需要针对 r 值进行优化,您可以考虑选项 2 并添加一个移动赋值运算符。

很容易考虑选项 3 和按值传递,然后移动,我认为这正是您的建议。在那种情况下,您只需编写一个赋值运算符。它接受 l 值,并且只需多走一步就可以接受 r 值,许多人会提倡这种方法。

然而,Herb Sutter 在他的 "Back to the Basics! Essentials of Modern C++ Style" 中指出在 CppCon 2014 上谈到这个选项有问题并且会慢得多。在左值的情况下,它将执行无条件复制并且不会重用任何现有容量。他提供了数字来支持他的说法。唯一的异常(exception)是构造函数,它们没有现有的重用能力,而且您通常有很多参数,因此按值传递可以减少所需的重载次数。

因此我建议您从选项 1 开始,如果您需要针对 r 值进行优化,则转到选项 2。

关于c++ - 使用哪个 : move assignment operator vs copy assignment operator,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26772146/

相关文章:

c++ - std::optional:不参与重载决议与被定义为已删除

c++ - 如何将一个类的函数添加到同一个类的另一个函数内的重载解析列表中?

delphi - 获取重载方法的地址位置

c++ - return 语句何时会中断函数?

c++ - Qt - MDI Child 未正确关闭

c++ - 使用 integer_sequence 过滤元组

c++ - 接收参数并为可能失败的函数 move 语义(强大的异常安全性)

c++ - 发送带有 syn 标志集的原始 tcp 数据包只是通过 lo 接口(interface),而不是我想要的 eth0

c++ - 访问指针的速度

c++11继承模板构造函数