左右值重载策略
有时我们需要在函数中区分参数的左右值属性,根据参数左右值属性的不同做出不同的处理。适当地采用左右值重载策略,借助于左右值引用参数不同的绑定特性,我们可以利用函数重载来做到这一点。常见的左右值重载策略如下:
struct X {};
//左值版本
void f(const X& param1){/*处理左值参数param1*/}
//右值版本
void f(X&& param2){/*处理右值参数param2*/}
X a;
f(a); //调用左值版本
f(X()); //调用右值版本
f(std::move(a)); //调用右值版本
即在函数重载中分别重载const左值引用和右值引用。
重载const左值引用的为左值版本,这是因为const左值引用参数能绑定左值,而右值引用参数不能绑定左值。
重载右值引用的为右值版本,这是因为虽然const左值引用参数和右值引用参数都能绑定右值,但标准规定右值引用参数的绑定优先度要高于const左值引用参数。
移动构造器和移动赋值运算符
在类的构造器和赋值运算符中运用上述左右值重载策略,就会产生两个新的特殊成员函数:移动构造器(move constructor)和移动赋值运算符(move assignment operator)。
struct X
{
X(); //缺省构造器
X(const X& that); //拷贝构造器
X(X&& that); //移动构造器
X& operator=(const X& that); //拷贝赋值运算符
X& operator=(X&& that); //移动赋值运算符
};
X a; //调用缺省构造器
X b = a; //调用拷贝构造器
X c = std::move(b); //调用移动构造器
b = a; //调用拷贝赋值运算符
c = std::move(b); //调用移动赋值运算符
移动语义
无名右值引用和具名右值引用的引入主要是为了解决移动语义问题。
移动语义问题是指在某些特定情况下(比如用右值来赋值或构造对象时)如何采用廉价的移动语义替换昂贵的拷贝语义的问题。
移动语义(move semantics)是指某个对象接管另一个对象所拥有的外部资源的所有权。移动语义需要通过移动(窃取)其他
对象所拥有的资源来完成。移动语义的具体实现(即一次that对象到this对象的移动(move))通常包含以下若干步骤:
如果this对象自身也拥有资源,释放该资源 将this对象的指针或句柄指向that对象所拥有的资源 将that对象原本指向该资源的指针或句柄设为空值上述步骤可简单概括为①释放this(this非空时)②移动that
移动语义通常在移动构造器和移动赋值运算符中得以具体实现。两者的区别在于移动构造对象时this对象为空因而①释放this无须进行。










