1. 左值 和 右值
举例:
int& func01() {
int a = 3;
return a; // 不能返回局部变量的引用
}
void test09() {
int a = 10; // a 左值,10 右值
int& b = a; // 正确
// int& c = 10; // 错误
const int& d = a; // 正确
const int& e = 1; // 正确
/*
相当于:
int tmp = 1;
const int& c = tmp;
*/
}
总结:
(a)左值可以取地址,右值不能取地址;
(b)右值:字面量、函数返回的非引用变量。
2. 右值引用
如下:
/*
右值引用只能绑定右值,左值引用只能绑定左值。
*/
int&& a = 10; // 正确,可将右值赋值给右值引用
int b = 20;
int&& c = b; // 错误,不可将左值赋值给右值引用
int&& d = a; // 错误,右值引用变量本身是左值
int& e = a; // 正确,可将右值引用变量赋给左值
3. 移动构造
简单来说就是资源转移,并未重新开辟内存空间。和右值引用密切相关。
个人认为和浅拷贝对比来说更易理解:浅拷贝是多个指针管理同一个资源,而移动构造则是在资源由原指针转移给新指针,而原指针置为nullptr,不再管理资源。
4. move移动语意和forward完美转发
move:得到右值类型,将资源管理权限转移。
forward:能够识别左值、右值,进而正确匹配到拷贝构造或移动构造。