当前位置 : 主页 > 编程语言 > c语言 >

深度解读C++引用

来源:互联网 收集:自由互联 发布时间:2023-09-07
什么是引用(reference) 引用不是新定义一个变量,而是给已存在对象取了一个别名,从语言逻辑角度看,引用不占用额外的内存空间,而与被引用的对象共用同一块内存空间。使用引用时

什么是引用(reference)

引用不是新定义一个变量,而是给已存在对象取了一个别名,从语言逻辑角度看,引用不占用额外的内存空间,而与被引用的对象共用同一块内存空间。使用引用时,需要注意以下几点:

  • 引用在定义时必须初始化;
  • 一个变量可以有多个引用;
  • C++中的引用一旦初始化便不能转移;
  • 在语法逻辑角度,引用不占用额外的内存空间,只是某个对象的别名。

深度解读C++引用_常引用

引用的使用场景(意义)

做参数

输出型参数

此时形参是实参的一个别名,形参的改变会影响实参,故可以用引用做输出型参数。相比指针,引用做输出型参数显得更加明了和方便。

void Swap(int& x, int& y)
{
	int tmp = x;
	x = y;
	y = tmp;
}

提高效率

传参时,使用引用可以避免参数的压栈过程,减少拷贝,以提高效率。当面对大对象和深拷贝类对象时,引用传参的效率提升非常明显。

做返回值

提高效率

由于函数栈帧会销毁,当函数返回一个值时,总是会先将返回值拷贝到一个临时变量中再返回。若返回返回值的引用,则可以避免该次拷贝而而直接返回该值以提高效率。

获取返回值

返回堆区或静态区的变量时,直接返回变量的引用不仅可以避免临时变量拷贝的开销,而且返回后可以直接对返回值进行修改,以减去一些其他冗余的操作。

struct SeqList
{
	int data[100];
	int sz;
};

int& SeqAt(SeqList& s, int pos)
{
	return s.data[pos];
}

int main()
{
	SeqList sq;
	//直接对返回值进行修改
	SeqAt(sq, 0) = 50;
	cout << sq.data[0] << endl;

	SeqAt(sq, 0) += 30;
	cout << sq.data[0] << endl;

	return 0;
}

用引用做返回值时需要注意的是,如果返回时,出了函数作用域返回对象的内存空间还未释放,则可以使用引用返回,如果内存已经释放了,则不能使用引用返回,此时返回的引用对象已被释放,内容不确定,属于非法访问。

关于常引用的问题

关于常引用的问题,涉及到引用的权限问题,引用的权限不能放大,只能平移或缩小,例如,不能以一个变量作为常量的引用,这是因为常量无法被修改,而变量可以被修改,也就是说权限被放大了,这是不允许的。

关于常引用还有会牵涉到其他细节:

  • 类型转换会产生一个临时变量,临时变量具有常属性,只能用常量进行引用;

深度解读C++引用_指针_02

double d = 3.14;
//int& i = d; // 权限放大
const int& i = d; //权限平移
  • 上文说到,函数值返回时,会先将返回值存储到一个临时变量中,临时变量具有常属性,所以返回值只能用常量进行引用。

深度解读C++引用_引用_03

int Add(int x, int y)
{
	return x + y;
}

int main()
{
	//int& rret = Add(12, 10); //权限放大
	const int& rret = Add(12, 10); //权限平移
	return 0;
}

引用的底层逻辑

上文说到,引用在语法层面上不占用独立空间,与被引用对象占用同一块空间,但通过观察底层汇编代码,可以发现引用的底层实现逻辑与指针相同,也就是说,从底层汇编角度看,引用是用类似指针的方式实现的。

深度解读C++引用_引用_04

虽然引用的底层是指针,但是在 C++ 中使用最多的依然是引用,这是因为相对于指针,引用往往更加明了和方便。

引用和指针的区别

  • 在语法层面上,引用不具有独立空间,与被引用对象占用同一块空间;指针存储一个对象的地址
  • 引用在定义时必须初始化;指针没有要求
  • 引用在初始化引用一个实体后就不能引用其它实体;指针可以随时改变指向而指向一个其它实体
  • 没有空引用;存在空指针
  • sizeof中的意义不同:计算引用的结果为被引用对象类型的大小;计算指针的结果始终为地址空间所占字节数(4字节或8字节)
  • 引用与常数运算,即被引用的对象进行运算;指针与常数进行(加减)运算,进行的是指针偏移(移动)
  • 有多级指针,但是没有多级引用
  • 访问实体的方式不同:指针需要显式解引用;引用编译器自行处理
  • 引用使用起来比指针更安全
上一篇:网络七层模型—网络层
下一篇:没有了
网友评论