使用哪个:移动赋值运算符与复制赋值运算符

Kam*_*Kam 7 c++ overload-resolution c++11

我似乎不明白为什么你会使用move assignment operator:

CLASSA & operator=(CLASSA && other); //move assignment operator
Run Code Online (Sandbox Code Playgroud)

结束了copy assignment operator:

CLASSA & operator=(CLASSA  other); //copy assignment operator
Run Code Online (Sandbox Code Playgroud)

move assignment operator接受一个r-value reference只有如

CLASSA a1, a2, a3;
a1 = a2 + a3;
Run Code Online (Sandbox Code Playgroud)

copy assignment operator,other可以是使用a copy constructor或a的构造函数move constructor(如果other用rvalue初始化,它可以是移动构造的 - 如果已move-constructor定义 - ).

如果是copy-constructed,我们将进行1份复制,并且无法避免该副本.

如果是,move-constructed那么性能/行为与第一次过载产生的性能/行为相同.

我的问题是:

1-为什么要实现move assignment operator.

2-如果 other是由r值构造的,那么assignment operator编译器会选择调用哪个?为什么?

Chr*_*rew 7

你不是在比较喜欢

如果您正在编写一个仅移动类型,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在他的"回归基础知识!现代C++风格的基本要素"中指出,在 CppCon 2014中,这个选项存在问题,而且速度要慢得多.在l值的情况下,它将执行无条件复制,并且不会重用任何现有容量.他提供数字来备份他的说法.唯一的例外是构造函数,其中没有现有的重用容量,并且您通常有许多参数,因此传递值可以减少所需的重载次数.

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