C++初阶语法——引用,从此和指针说byebye

前言:相信学过C语言的同学肯定被指针深深折磨过,从一级指针到二级指针,数组指针,函数指针等等,可谓是谈针色变。而在C++中,使用引用代替了指针的使用,大大降低了我们学习的难度。

一.什么是引用

引用并不是新定义了一个变量,而是给已经存在的变量取了个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间
以孙悟空为例,他又叫做齐天大圣,斗战胜佛,所以我们说齐天大圣就能想到孙悟空。
格式:类型& 引用变量名 = 引用实体

可以看到,a和b的地址是一样的。在这里插入图片描述#

二.引用的特性(限制)

1.引用在定义时必须初始化
2.一个变量可以有多个引用
3.引用一旦引用一个实体,就不能再引用其它实体(这点与指针略有不同,因为指针是可以改变指向的对象的)

void test()
{
    
    
	int a = 10;
	int b = 20;
	//int& ra;  //编译出错,引用在定义时必须初始化
	int& ra = a;
	int& rra = a;  //ra,rra都是a的别名,地址是一样的。
	//int& ra = b;  //ra已经是a的别名,不能再作为其它变量的别名。
}

三.传引用传参(引用做参数)

我们知道C语言中用函数交换两个变量需要传址调用,而在C++中可以直接用引用替代,方便理解的同时也不需要在进行解引用,这在存在二级及以上指针的时候极大地提高了代码的可读性。

//C语言写法
//void Swap(int* a, int* b)
//{
    
    
//	int tmp = *a;
//	*a = *b;
//	*b = tmp;
//}

//引用C++写法
void Swap(int& a, int& b)
{
    
    
	int tmp = a;
	a = b;
	b = tmp;
}
int main()
{
    
    
	int a = 10;
	int b = 20;
	Swap(a, b);
	cout << "a = " << a << endl;   // 20
	cout << "b = " << b << endl;   // 10
	return 0;
}

四.传引用返回(引用做返回值)

这是一个重点内容,在后续学习默认成员函数时会经常出现。
先说结论:如果函数返回时,出了函数作用域,如果返回对象还在,则可以使用引用返回,否则必须使用传值返回。

1.传值返回(与传引用返回对比)

请看这段代码,你觉得打印ret会显示什么? 答:1
函数栈帧销毁,在使用传值返回时会使用临时变量存储n,临时变量具有常属性

这里是引用

2.传引用返回

问:打印ret会显示什么?
传引用返回,返回的是n的别名,但是函数栈帧已经销毁了,因此这时候ret有两种情况,随机值或者是1,这取决于这块栈帧空间是否被重置。(博主在VS上运行结果是1)
这里是引用

3.传引用返回示例

使用传引用返回可以简化操作,如下例代码,原本顺序表的查找和修改两个接口通过传引用返回可以直接合并成一个接口

扫描二维码关注公众号,回复: 16573537 查看本文章
typedef struct Seqlist {
    
    
	int* a;
	int capacity;
	int size;
}SL;
//C接口设计
//返回第i个位置的值
int SLFind(SL* Seq, int i)
{
    
    
	assert(i < Seq->size);
	//...
	return Seq->a[i];
}
//修改第i个位置的值
void SLModify(SL* Seq, int i,int x)
{
    
    
	assert(i < Seq->size);
	//...
	Seq->a[i] = x;
}

//C++接口设计
int& SLFM(SL* Seq, int i)
{
    
    
	assert(i < Seq->size);
	//...
	return Seq->a[i];
}
int main()
{
    
    
	SL* s1;
	//SLFind(s1,2) = 10  // 不可行,因为传值返回的值具有常属性,不能被修改。
	SLFM(s1, 2) = 10; //将第2个位置的值修改成10
	return 0;
}

五.引用权限问题

对于具有常属性的变量等需要注意:在使用引用时,权限可以缩小,平移,但是不能放大。

int main()
{
    
    
	const int a = 10;
	int ar = a;  //这是单纯的赋值,不存在权限问题。
	//int& b = a;  //权限放大,原本a具有常属性,但是别名b没有,将a的权限放大了。
	const int& c = a; // 权限平移,a,c都具有常属性
	int x = 20;
	const int& d = x;  //权限缩小,别名d具有常属性,而引用实体x没有,将x的权限缩小了。
	return 0;
}

拓展:

以下代码你知道错在哪里吗?
在这里插入图片描述
或许有读者会认为是类型不匹配,实则不然:这里的错误是权限放大,加上const就不会标红了。
在这里插入图片描述
原因:x是int类型,而i是double类型,会发生类型转换,将x给给一个double类型的临时变量,而临时变量具有常属性,因此如果不加const就会发生权限放大。

文末BB:对哪里有问题的朋友,尽管在评论区留言,若哪里写的有问题,也欢迎朋友们在评论区指出,博主看到后会第一时间确定修改。最后,制作不易,如果对朋友们有帮助的话,希望能动动你们发财的小手给点点赞和关注.
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_73390155/article/details/132154708