左值与右值

https://zhuanlan.zhihu.com/p/85668787

  • 左值:占用了一定内存,且拥有可辨认的地址的对象
  • 右值:左值以外的所有对象

右值引用是C++11中引入的新特性 , 它实现了转移语义和精确传递。它的主要目的有两个方面:

  1. 消除两个对象交互时不必要的对象拷贝,节省运算存储资源,提高效率。

  2. 能够更简洁明确地定义泛型函数。

引用(注意左值引用)

1
2
3
4
5
6
7
int i;
int &r = i;
int &r = 5; // 错误,不能左值引用绑定右值

// const 引用是例外
// 可以认为指向一个临时左值的引用,其值为5
const int &r = 5;

右值引用

用途:

  • 移动语义
  • 完美转发

移动语义

移动语意(std::move),可以将左值转化为右值引用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
int a = 1; // 左值
int &b = a; // 左值引用

// 移动语意: 转换左值为右值引用
int &&c = std::move(a);

void printInt(int& i) {
cout << "lval ref: " << i << endl;
}
void printInt(int&& i) {
cout << "rval ref: " << i << endl;
}

int main() {
int i = 1;

// 调用 printInt(int&), i是左值
printInt(i);

// 调用 printInt(int&&), 6是右值
printInt(6);

// 调用 printInt(int&&),移动语意
printInt(std::move(i));
}

完美转发

完美转发是指

  • 只有在需要的时候,才调用复制构造函数
  • 左值被转发为左值,右值被转发为右值

右值引用和左值引用的区别

  1. 左值可以寻址,而右值不可以。

  2. 左值可以被赋值,右值不可以被赋值,可以用来给左值赋值。

  3. 左值可变,右值不可变(仅对基础类型适用,用户自定义类型右值引用可以通过成员函数改变)。