1.左值和右值
可以取地址的值就是左值,左值通常带名字;
不可以取地址的值就是右值,右值通常匿名
#include <iostream> using namespace std; int& foo (int& a) { return a; } int bar (int& a) { return a; } int main (void) { // 左值,可取地址 int a, b = 0; cout << &a << endl; // 有名变量 cout << &foo (a) << endl; // 引用形式的函数返回值 cout << &++a << endl; // 前缀自增减表达式的值 cout << &(a=b) << endl; // 赋值类表达式的值 /* 右值,不可取地址 cout << &10 << endl; // 字面值常量 cout << &bar (a) << endl; // 值形式的函数返回值 cout << &a++ << endl; // 后缀自增减表达式的值 cout << &(a+b) << endl; // 运算表达式的值 cout << &(double)a << endl; // 类型转换表达式的值 */ /* 所有的右值天然具备只读属性 10 = 10; bar (a) = a; a++++; a+b=10; (double)a = 1.23; */ // 以上右值亦称纯右值,另一种右值称为将亡右值 return 0; }
2.左值引用和右值引用
(1)左值引用只能引用左值,不能引用右值
类型 &左值引用=左值
int a;
int &lvr=a;
int &lvr=10;//error
(2)右值引用只能引用右值,不能引用左值
类型 &&右值引用=右值;
int a;
int &&rvr=10;
int &&rvr=a; //error
(3)常左值引用,万能引用,既能引用左值,也可以引用右值
int a;
int const &lvr=10;
int const &lvr=a;
(4)任何临时值只具语句级生命周期,引用可将其寿命延长,延长至和该引用的生命期一样
#include <iostream> using namespace std; class A { public: A (void) { cout << "A构造:" << this << endl; } A (A const& that) { cout << "A拷贝:" << &that << "->" << this << endl; } ~A (void) { cout << "A析构:" << this << endl; } }; A foo (void) { A a; return a; } int main (void) { int a = 1, b = 2; int& lvr1 = a; /* 左值引用不能引用右值 int& lvr2 = a + b; */ int&& rvr1 = a + b; /* 右值引用不能引用左值 int&& rvr2 = a; */ int const& clvr1 = a; int const& clvr2 = a + b; cout << "-------- 1 --------" << endl; foo (); cout << "-------- 2 --------" << endl; A&& rvra = foo (); // rvra ... cout << "-------- 3 --------" << endl; return 0; }
3.通用引用
(1)在函数模板隐式推断过程中,若实参为左值,则T&&被推断为左值引用,若实参为右值,则T&&被推断为右值引用,这样的引用被称为通用引用
(2)只有T&&才是通用引用,加了const就不是了