我似乎不明白为什么要使用移动赋值运算符
:
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
这样的只能移动的类型,那么移动赋值运算符将是您唯一的选择。
更典型的情况是你有一个可复制的类型,在这种情况下我认为你有三个选择。
T& operator=(T const&)
T& operator=(T const&)
和T& operator=(T&&)
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/