function3-左值右值
前言
在C语言中什么叫左值和右值
1 | int a = 3; |
- 左值一般是变量,在程序运行时有一个准确的地址和值,除了const的情况下一般都能修改。
- 右值则一般是常量或者临时对象,除非强转之类的操作,其它情况下一般不能修改
在编译报错的时候应该或多或少也见过到提示右值不可被修改
不过上述的说法也并不绝对
1 | int a = 1; |
这里的右值b它是一个变量。
正文
1 | void AddSum(int a){ |
在正常情况下,int a = 10; 编译器把10转换成十六进制赋值给ebp-8的位置上
而调用函数传参的时候使用算术表达式他也会默认先算好,可能这里函数的反汇编不明显
稍微改动一下让a+10+20
这里就很清楚的看到编译器先将ebp-8的地址传给eax寄存器,然后eax寄存器在加上1E,也就是30
正常的变量作为左值都好解释,数组和指针的时候:
1 | int array[10]; |
左值引用和右值引用
1 | int a = 10; |
编译器提示无法将 右值引用绑定到左值,
那么两个&该怎么用:
1 | int &&c = 150+120; |
显然是给他引用一个右值为这种算术表达式。但是注意修改c没有太大意义,因为右值是固定的。
那么右值引用的场景在哪。
1 | void AddSum(int &a){ |
当函数参数为左值引用时,没办法传递表达式进去,所以右值引用的场景就来了
1 | void AddSum(int &&a){ |
当然可以先用一个变量接受这个表达式:
1 | void AddSum(int &a){ |
这个是没啥问题,语义是通顺的。
int x毕竟是额外开辟了内存空间去保存这个表达式的值,虽然临时变量也会占内存,但是至少临时变量销毁比局部变量快。
题外话
&在C语言中,我们通俗的说是取地址符,而在cpp中多了引用的概念
区分的方式就是 参照 =
当& 在变量定义区域,表示引用:int &b = a
当& 在变量操作区域,表示取地址:int *p = &a;
然后来个玄乎的 &*p 和 *&p
,在变量定义区域时:
1 | int a = 10; |
int *&p1 = p
先当与指向一个引用,指针引用。int &*p2 = p
引用一个指针显然是不对的。引用本身就是一个弱化版本的指针,编译器也提示错误
在变量操作时:
1 | int a = 10; |
修改成指针呢?
1 | int a = 10; |
可以看到地址都是一样的。
这个纯看理解,不行多试几个例子或者看看反汇编。重在能区分。
结语
自古指针都是很恶心的东西,不管放到哪里。要合理区分&是引用还是取地址的情况。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Box'Blog!
评论