前言
对于C++的左值引用和右值引用的介绍不是很了解,找了几篇文章,然后简单的记录一下。
这里只是记录大概,暂时不深入,想深入看的请看参考文吧。
正文
左值和右值
左值
左值是一个表示数据的表达式,比如:变量名、解引用的指针变量。
总体而言,可以取地址的对象就是左值!
int a = 5; int *p = &a; const int b = 2;
a,p和b都是左值。
右值
右值也是一个表示数据的表达式,比如:字面常量、表达式返回值,传值返回函数的返回值(是传值返回,而非传引用返回),右值不能出现在赋值符号的左边且不能取地址。
总体而言,不可以取地址的对象就是右值,也不可以修改右值!
10; // 字面常量 x + y; // 表达式返回值 myAdd(x, y); // 传值返回函数的返回值
上面10,x+y,myAdd(x,y)都是右值。
右值放在=左边就会报错提示,提示[表达式必须是可修改的左值];对其取地址也会报错,提示[表达式必须为左值或函数指示符]。
总结
可位于赋值号(=)左侧的表达式就是左值;反之,只能位于赋值号右侧的表达式就是右值。
左值一般是我们自己定义的编译,在定义时开辟了内存,我们可以对这块内存赋值,也可以修改内存中的值。
C++中的左值也可以当作右值使用。
int a = 5; // a是一个左值 int b = 10; // b 是一个左值 a = b; // a、b 都是左值,只不过将 b 可以当做右值使用
有名称的、且可以获取到存储地址的表达式即为左值;反之则是右值。
上面变量 a、b 是变量名且通过 &a 和 &b 可以获得他们的存储地址,因此 a 和 b 都是左值;反之,字面量 5、10,它们既没有名称,也无法获取其存储地址(字面量通常存储在寄存器中,或者和代码存储在一起),因此 5、10 都是右值。
右值的生命周期一般只在当前语句。
右值一般为临时变量,是程序运行时产生的中间产物,他不是我们用户自己定义开辟空间的,是由编译器帮我们开辟空间,并且在用完就立即销毁。
当然,最简单的判断左值或右值,就看他是否可以取地址。
左值引用 和右值引用
左值引用
左值引用就是给左值的引用,给左值(对象)取别名。
“&”表示的引用又称为左值引用。
作用是避免对象拷贝。
int c = 0; const int b = 2; int* p = nullptr; //左值引用 int& lc = c; const int& lb = b; int*& lp = p;
右值引用
右值引用就是给右值的引用,给右值(对象)取别名。
C++11 标准新引入了另一种引用方式,称为右值引用,用 “&&” 表示。
作用是把延长对象的生命周期,一般是延长到作用域的scope之外
int fun(){ return 1; } void test(){ int a = 1, b = 2; //右值引用 int && r1 = 10; int && r2 = (a + b); int && r3 = fun(); }
总结
非常量左值引用可以引用的值的类型只有非常量左值,常量左值引用非常量左值、常量左值及右值
int num = 10; int& a = num; //编译成功,非常量左值引用支持引用非常量左值 const int num2 = 100; int& b = num2; //编译失败,非常量左值引用不支持引用常量左值 int& c = 10; //编译失败,非常量左值引用不支持引用右值 const int& d = num; //编译成功,常量左值引用支持引用非常量左值 const int& e = num2; //编译成功,常量左值引用支持引用常量左值 const int& f = 100; //编译成功,常量左值引用支持引用右值
右值引用不支持引用左值;非常量右值引用可以引用的值的类型只有非常量右值,常量右值引用非常量右值、常量右值
int num = 10; const int num2 = 100; int&& a = num; //编译失败,非常量右值引用不支持引用非常量左值 int&& b = num2; //编译失败,非常量右值引用不支持引用常量左值 int&& c =10; //编译成功,非常量右值引用支持引用非常量右值 const int&& d = num; //编译失败,常量右值引用不支持引用非常量左值 const int&& e = num2; //编译失败,常量右值引用不支持引用常量左值 const int&& f = 100; //编译成功,常量右值引用支持引用右值
参考文章
《》
《》
《