3. 右值引用

右值引用C++11 引入的一种新的引用类型,用 T && 表示,它用于代替使用 const 类型的左值引用(const T &)来绑定右值,给右值取一个别名,延长右值的生命周期,同时可以窃取右值的资源,从而避免复杂的深拷贝来提高执行效率。

语法

类型 && 引用变量名 = 右值;

示例

#include <iostream>

using namespace std;

int main(int argc, char * argv[]) {
    int x = 100;
    int &lr_x = x; // 左值引用
    // int &lr_e = 200; // 错误,左值引用不能绑定左值
    const int &clr = 300; // const 左值引用可以绑定右值(延长生命周期)
    int && rr_1 = 400; // 右值引用绑定右值 
    int && rr_2 = x + 1; // 右值引用绑定右值 
    // int && rr_3 = x; // 错误右值引用不能绑定左值 

    return 0;
}

移动语义 std::move

std::move 是 C++11 中一个纯粹的强制类型转换(static_cast),作用是把左值类型无条件转换为右值类型,从而 告诉 编译器,此std::move 函数返回的类型是右值,在函数重载时最匹配的类型是右值引用。

用法:

std::move(obj)  // 可以将一个左值(或右值)将其转化为右值。

函数重载决议优先级顺序

  1. 精确匹配
  2. 左值/右值引用匹配
  3. 常量转换
  4. 其他转换

示例

// filename: override.cpp
#include <iostream>

using namespace std;


void fx(int &x) {
    cout << "fx(int &x):" << x << endl;
}
void fx(const int &x) {
    cout << "fx(const int &x):" << x << endl;
}
void fx(int &&x) {
    cout << "fx(int &&x):" << x << endl;
}
void fx(double x) {
    cout << "fx(double x):" << x << endl;
}

int main(int argc, char * argv[]) {
    // 右值
    int i = 100; // r是右值
    int &ri = i;  // ri左值引用
    const int & cri = i; //  cri 是带有const 修饰属性的左值引用
    fx(i);  // 调用 void fx(int &x);
    fx(ri);  // 调用 void fx(int &x);
    fx(cri);  // 调用 void fx(const int &x);
    fx(200);  // 调用 void fx(int &&x);
    fx(cri+1);  // 调用 void fx(int &&x);
    fx(1+2);  // 调用 void fx(int &&x);
    fx(std::move(i));  // 调用 void fx(int &&x);

    return 0;
}

编译和运行结果如下:

weimz@mzstudio:~$ g++ -o override override.cpp
weimz@mzstudio:~$ ./override 
fx(int &x):100
fx(int &x):100
fx(const int &x):100
fx(int &&x):200
fx(int &&x):101
fx(int &&x):3
fx(int &&x):100