c++之左值
2016-05-06 01:01
561 查看
左值是c++中的一个基本概念,凡是可以出现在赋值运算左边的表达式都是左值。右值跟左值相对,凡是可以出现在赋值运算右边的表达式都是右值。
左值一定可以作为右值,而反过来不一定成立。
(2)非只读单元
(3)不能是临时无名对象 如: i+1 =5 不行
(4)如果表达式运算结果是一个引用,可以作为左值。 如:int &fun() 函数可以,(i+=1)=5 可以,i+=运算结果是对i的引用
由此可知:
(1)并不是只有单个变量才能作为左值
(2)也不能仅由表达式的外在形式判断是否为左值。要根据一个表达式的运算结果的性质判断。
结合引用的性质可知:
(1)能建立普通引用的表达式一定是左值;
(2)不能作为左值的表达式只能建立常引用,而不能建立普通引用。
函数的参数声明为引用,这样在发生函数调用时可以减少运行时开销。将函数的参数声明为一般的引用还是声明为常引用很有讲究。
以上代码编译不通过,显示“非常引用的初始值必须为左值”,由于5不是左值,不能为它建立普通引用,所以编译错误。于是在此时修改函数定义
可见:
将函数的参数声明为常引用,不完全是因为参数的值在函数体内不能修改,还可能是接受非左值作为函数参数的情况。
输出:
如果将下句的const去掉则会报错。原因是普通引用只能建立在相同的数据类型变量上。同样,能允许 Max(rc,5.5) 这样的函数调用也是因为函数 Max() 的第二个参数是常引用,因此将实参 5.5 先转换为 int 型无名变量,然后再建立对该无名变量的常引用。
(2)其次还要考虑表达式结果的数据类型与引用数据类型是否一致
否则只能另外建立一个无名变量,该变量中存放非左值表达式的运算结果,然后再建立对该无名变量的常引用。
不过既然这里建立的是一个临时的无名变量,但这个变量同时也占用栈空间,那就可以相办法改变,而且改变这个值不会改变原有的变量:
输出:
左值一定可以作为右值,而反过来不一定成立。
左值概念有:
(1)必须可寻址(2)非只读单元
(3)不能是临时无名对象 如: i+1 =5 不行
(4)如果表达式运算结果是一个引用,可以作为左值。 如:int &fun() 函数可以,(i+=1)=5 可以,i+=运算结果是对i的引用
由此可知:
(1)并不是只有单个变量才能作为左值
(2)也不能仅由表达式的外在形式判断是否为左值。要根据一个表达式的运算结果的性质判断。
结合引用的性质可知:
(1)能建立普通引用的表达式一定是左值;
(2)不能作为左值的表达式只能建立常引用,而不能建立普通引用。
函数的参数声明为引用,这样在发生函数调用时可以减少运行时开销。将函数的参数声明为一般的引用还是声明为常引用很有讲究。
int Max(int &a,int &b) { return (a>b)?a:b; } int main() { //freopen("input.txt","r",stdin); int i=2; cout<<Max(i,5)<<endl; return 0; }
以上代码编译不通过,显示“非常引用的初始值必须为左值”,由于5不是左值,不能为它建立普通引用,所以编译错误。于是在此时修改函数定义
int Max(int &a,const int &b);
可见:
将函数的参数声明为常引用,不完全是因为参数的值在函数体内不能修改,还可能是接受非左值作为函数参数的情况。
常引用类型转换
对某个变量(或表达式)建立常引用,允许发生类型转换,而一般的引用不允许int Max(const int &a,const int &b) { return (a>b)?a:b; } int main() { //freopen("input.txt","r",stdin); char c='a'; const int &rc = c; PRINT((void*)&c); PRINT((void*)&rc); int i=7; const int &ri = i; PRINT((void*)&i); PRINT((void*)&ri); cout<<Max(rc,5.5)<<endl; return 0; }
输出:
如果将下句的const去掉则会报错。原因是普通引用只能建立在相同的数据类型变量上。同样,能允许 Max(rc,5.5) 这样的函数调用也是因为函数 Max() 的第二个参数是常引用,因此将实参 5.5 先转换为 int 型无名变量,然后再建立对该无名变量的常引用。
const int &rc = c;
对表达式建立常引用:
(1)首先要考虑该表达式结果是否能寻址(2)其次还要考虑表达式结果的数据类型与引用数据类型是否一致
否则只能另外建立一个无名变量,该变量中存放非左值表达式的运算结果,然后再建立对该无名变量的常引用。
不过既然这里建立的是一个临时的无名变量,但这个变量同时也占用栈空间,那就可以相办法改变,而且改变这个值不会改变原有的变量:
int main() { //freopen("input.txt","r",stdin); char c='a'; const int &rc = c; PRINT(c); PRINT(rc); PRINT((void*)&c); PRINT((void*)&rc); int dis = (int)&rc-(int)&c; PRINT(dis); int* addr = (int*)((int)&c+dis); //精确计算rc指向的无名变量的地址 *addr = 666; PRINT(c); PRINT(rc); return 0; }
输出:
相关文章推荐
- leetcode_c++:Median_of _two_sorted_arrays(004)
- 在VC++6.0中安装Allegro游戏图形库
- iOS-C语言知识点串讲
- c语言中的参数传递问题(传value)
- c++ 1
- C++标准输入
- Effective C++: user-defined deleter.
- #奇葩论--在C语言中利用函数递归创建链表#
- More Effective C++----(14)审慎使用异常规格(exception specifications)
- More Effective C++----(13)通过引用捕获异常
- c++内存
- C++1
- 关于C语言的"[]"运算符与指针
- More Effective C++----(12)理解"抛出一个异常"与"传递一个参数"或"调用一个虚函数"间的差异
- C++重复模板实例的处理
- c++ 课堂作业(1)
- 一起talk C栗子吧(第一百四十六回:C语言实例--socket属性)
- C++开学第一次作业(5.4)
- C++作业 一
- C++第一次试水写cstring类