箭头运算符和点运算符的左右值

C++ primer(英文第5版)的150页介绍了两个成员访问运算符:箭头运算符(->)和点运算符(.)。关于他们产生的是左值还是右值,书中有:

The arrow operator requires a pointer operand and yields an lvalue. The dot operator yields an lvalue if the object from which the member is fetched is an lvalue; otherwise the result is an rvalue.


1
2
3
4
5
A *p = new A;
A a;
p -> n; //左值
a.n; //左值

这就有点奇怪了,明明箭头运算符和点运算符实现的是类似的功能,但结果的左右值可能不同。
其主要区别在于箭头运算符(转化为等价的点运算符后)和点运算符的左边的运算对象是否是左值,即判断*p和a是否是左值:

  1. 如果是,那么返回结果是左值
  2. 如果不是,那么返回结果是右值

有了这概念,就好理解了,因为箭头运算符的左边的运算对象(*p)一定是左值,所以他的结果就是左值;而点运算符的左边的运算对象不一定是左值,所以有可能是左值,也有可能是右值。

举个例子:

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
26
27
28
29
30
31
#include <iostream>
using namespace std;
struct A
{
int n; //struct默认是public,class默认是private
A() = default;
A(int m): n(m) {}
};
int main()
{
A st(5);
A* pst = &st;
cout << st.n << endl; //输出5,st是左值,在该表达式执行完毕后依然存在
st.n = 6; //合法,可以对左值赋值
cout << pst->n << endl; //输出6,pst是左值,在该表达式执行完毕后依然存在
pst->n = 7; //合法,可以对左值赋值
cout << A(8).n << endl; //输出8,A(8)是右值,在该表达式执行完毕后被销毁
A(8).n = 9; //非法,不能对右值赋值
pst = &(A(8)); //非法,不能取右值的地址
return 0;
}
作者:573xmcgcg
链接:https://www.zhihu.com/question/35776952/answer/64411299/
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。