目录

CD7.C-Dev引用reference-下

CD7.【C++ Dev】引用&(reference) 下


承接 文章

1.练习1

下面代码是否有问题?

int function1()
{
	static int x = 0;
	return x;
}

int main()
{
	int& ret = function1();
	return 0;
}

有引用,可能出现权限的问题 ,这里权限 放大

return x;由于返回类型为int,而返回值由临时变量接收,临时变量具有常属性(只可读),那么使用int&来接收属于权限的放大

(从只可读放大成可读可写),是不被允许的

改法1:权限的平移

int function1()
{
	static int x = 0;
	return x;
}

int main()
{
	const int& ret = function1();
	return 0;
}

用const修饰,变成具有常属性,

权限可以平移

改法2:直接复制返回值

不使用引用&,直接复制返回值

int function1()
{
	static int x = 0;
	return x;
}

int main()
{
	int ret = function1();//ret可读可写
	return 0;
}

2.练习2

对于如下函数其接收返回值有几种写法?

int& function2()
{
	static int x = 0;
	return x;
}

写法1:权限的平移

int main()
{
	int& ret = function2();
    return 0;
}

function2()返回的是x的别名,因此使用int&同级接收(平移权限)

权限不变,即可读可写

写法2:权限的缩小

int main()
{
	const int& ret = function2();
    return 0;
}

权限从可读可写变成只可读(const修饰)

3.函数返回值(临时变量)分析

对比练习1和练习2函数返回值的接收方式

debug+x64平台下

function1:

https://i-blog.csdnimg.cn/direct/e80e8f7c0ab649439a8d17117ef21cc5.png

直接返回x的值

function2:

https://i-blog.csdnimg.cn/direct/78f3680aab734439bd1dabbc12acce7c.png

返回x的地址(

引用在底层上是指针数学的 )

临时变量的其他场景

例如隐式类型转换:

int main()
{
	int i = 1;
	double d = 3.14;
	if (i > d)
	{
		return 1;
	}
    return 0;
}

if在比较i和d时候,发现i和d是不同的类型,只有相同类型才能比较大小,因此int类型的i会被提升为double类型, 提升的结果暂时存储到临时变量(其实是寄存器)中,但i仍然为int类型

debug+x64反汇编代码分析:

https://i-blog.csdnimg.cn/direct/e3ae59aa37744ee3996be38db6564aa4.png

解析两个指令:

1.cvtsi2sd 网站的部分描述

https://i-blog.csdnimg.cn/direct/b072da0e1c444067b765ee72687acedb.png

简要作用:将双字整型转换为双精度浮点型

则可知

cvtsi2sd xmm0,dword ptr [i] 作用为:将i的值转换为double类型存储到xmm0寄存器中

2.comisd:下图截取了 网站的部分描述

https://i-blog.csdnimg.cn/direct/a7ec0dc517eb492d9941363d7edf4f15.png

简要作用:

比较双精度浮点型值 并设置EFLAGS标志寄存器

则可知

comisd xmm0,dword ptr [d] 作用为:比较转换成双精度的i和d的值

4.引用实质的两个角度的理解

角度1:语法层面未开空间 角度2:底层开了空间

分析底层开了空间

比较分割线上下两段代码,在底层上是否有区别?

int main()
{
	int a = 1;
	int& b = a;
	//=============
	int c = 2;
	int* pc = &c;
    return 0;
}

解:观察反汇编指令

	int a = 1;
 mov         dword ptr [a],1  
	int& b = a;
 lea         rax,[a]  
 mov         qword ptr [b],rax  
	//=============
	int c = 2;
 mov         dword ptr [c],2  
	int* pc = &c;
 lea         rax,[c]  
 mov         qword ptr [pc],rax  

上下两段代码的格式完全一样,引用和一级指针的写法没有区别,底层的引用是存储a的地址到b中

5.面试题:分析引用和指针的区别

概念上
引用定义一个变量的别名,指针存储一个变量地址
初始化上
引用在定义时必须初始化,指针没有要求
引用的特殊性
引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体
是否可为NULL
没有NULL引用,但有NULL指针
sizeof含义
引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)
运算
例如引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
是否有多级
有多级指针,但是没有多级引用
访问实体方式
指针需要显式解引用,引用编译器自己处理
安全性
引用比指针使用起来相对更安全