左值与右值

c++中的左值与右值、左值引用与右值引用。

左值与右值

左值与右值的概念

左值指既能够出现在等号左边,也能出现在等号右边的变量;右值则是只能出现在等号右边的变量。

1
2
3
int a = 10;//a是左值,10是右值
int b = a;// b是左值
int c = a + b;//a+b是右值

左值

左值具有以下特征:

  • 可通过取地址运算符获取其地址
  • 可修改的左值可用作内建赋值和内建符合赋值运算符的左操作数
  • 可以用来初始化左值引用

常见的左值:

  • 变量名、函数名以及数据成员名
  • 返回左值引用的函数调用
  • 由赋值运算符或复合赋值运算符连接的表达式,如(a=b, a-=b等)
  • 解引用表达式*ptr
  • 前置自增和自减表达式(++a, ++b)
  • 成员访问(点)运算符的结果
  • 由指针访问成员( -> )运算符的结果
  • 下标运算符的结果([])
  • 字符串字面值(“abc”)
1
2
3
4
5
6
7
8
9
10
11
12
13
int a = 1; // a是左值
T& f();
f();//左值
++a;//左值
--a;//左值
int b = a;//a和b都是左值
struct S* ptr = &obj; // ptr为左值
arr[1] = 2; // 左值
int *p = &a; // p为左值
*p = 10; // *p为左值
class MyClass{};
MyClass c; // c为左值
"abc"

右值

以下表达式的值都是纯右值:

  • 字面值(字符串字面值除外),例如1,’a’, true等
  • 返回值为非引用的函数调用或操作符重载,例如:str.substr(1, 2), str1 + str2, or it++
  • 后置自增和自减表达式(a++, a–)
  • 算术表达式
  • 逻辑表达式
  • 比较表达式
  • 取地址表达式
  • lambda表达式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
nullptr;
true;
1;
int fun();
fun();

int a = 1;
int b = 2;
a + b;

a++;
b--;

a > b;
a && b;

左值引用和右值引用

在C++11之前,引用分为左值引用和常量左值引用两种,但是自C++11起,引入了右值引用,也就是说,在C++11中,包含如下3中引用:

  • 左值引用
  • 常量左值引用(不希望被修改)
  • 右值引用

在C++11中引入了右值引用,因为右值的生命周期很短,右值引用的引入,使得可以延长右值的生命周期。在C++中规定,右值引用是&&即由2个&表示,而左值引用是一个&表示。C++11中右值引用可以实现“移动语义”。右值引用的作用是为了绑定右值

1
2
3
4
5
6
7
8
int a = 1;
int &rb = a; // rb为左值引用
int &&rrb = a; // 错误,a是左值,右值引用不能绑定左值
int &&rrb1 = 1; // 正确,1为右值
int &rb1 = i * 2; // 错误,i * 2是右值,而rb1为左值引用
int &&rrb2 = i * 2; // 正确
const int &c = 1; // 正确
const int &c1 = i * 2; // 正确

参考链接:

深入理解左值和右值 - 知乎 (zhihu.com)

理解 C/C++ 中的左值和右值 | nettee 的 blog


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!