在写引用类型与指针的比较这篇随笔的时候,我写了一些试验性的代码以检验一些结论是否正确。
首先,引用是一个const的指针(注意不是指向const object的指针),所以在声明一个引用的同时必须对这个引用进行初始化。因此
编译不能通过是自然而然的事情,错误信息是:references must be initialized。多事的我就想,既然是const的指针,那我能不能这么写呢:
结果错误信息变成了const object must be initialized if not extern。接着我再给这个statement加了个extern。OK,编译错误没有再出现了,接着,我给这个指针进行赋值。结果出现了这样的编译错误:
l-value specifies const object。
到此为止,我看到了一个似懂非懂的东西l-value。 到底什么是l-value呢?我第一时间想到左结合了,譬如说"hello" + "world" + "!" 等价于("hello" + "world") + "!"。由此推广,我可以想到的左值的一个解释就是:在赋值的时候,"="运算符左边的就是左值了。
而事实上,我的猜测也是基本正确的。左值必须引用于某个对象,而对于赋值运算符,它的左操作数必须是一个左值(lvalue expression must refer to an object.For the assignment to be valid, the left operand must refer to an object-it must be an lvalue. [1] );而右值(rvalue)则是具体的数字型或是字符型的值(Every expression is either an lvalue or an rvalue." So an rvalue is any expression that is not an lvalue. [1])。
以下是对于左值和右值在使用上的几个要点:
1、右值是不能转化为左值的,而反过来,则是可以的。如:
a = b;
a和b都是左值,但是b出现在了赋值运算符的右边。编译器在编译过程中做了左值到右值的转换。
2、"+"运算符的操作数没有左值或是右值的限制,但是运算的结果却是右值。比如说:
是会发生编译错误的,因为m + 1是右值;
3、"&"运算符的操作数必须是左值,而结果也是右值(注意这是取址运算符哦,别跟引用搞混了);
4、"*"运算符的操作数则左值或着右值,其结果则是左值,如
int * p = new int [ 3 ];
* p = a;
* (p + 1 ) = 3 ;
[1] Lvalues and Rvalues