(二)C++基础之引用的探究

1.1、使用引用四个知识点需要明白

1  引用没有定义,是一种关系型声明。声明它和原有某一变量(实体)的关系。故  而类型与原型保持一致,且不分配内存。与被引用的变量有相同的地址。  
2  声明的时候必须初始化,一经声明,不可变更。
3  可对引用,再次引用。多次引用的结果,是某一变量具有多个别名。 
4  &符号前有数据类型时,是引用。其它皆为取地址。

1.2、引用的本质

首先我们来测试一下引用占用多大字节

#include <iostream>

using namespace std;

struct test_a{
	int &a;
};

struct test_b{
	int *p;
};

int main(void)
{
	
	cout << "引用大小:" << sizeof(struct test_a) << endl;
	cout << "指针大小:" << sizeof(struct test_b) << endl;

	return 0;
}

运行结果:
在这里插入图片描述
在同为整形的前提下,他们都是占用四个字节,可是在这边看来指针是可以修改的指向别的变量,但是引用不行。

#include <iostream>

using namespace std;


int main(void)
{

	int a = 10;
	int b = 40;
	int *p;

	int &re = a;

	re = b;

	p = &b;

	*p = 80;

	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "re = " << re << endl;
	cout << "*p = " << *p << endl;


	return 0;
}

运行结果:
在这里插入图片描述
我们来分析一下这个结果,因为引用在一开始就初始化为某个变量的别名,也就是a的别名,之后将不再改变。

re = b;

对于这个语句,我们初衷的是将re作为b的别名,但是实际上此刻的re就已经代表a了,所以这个语句相当于。

a = b;

所以就有 a = 40 的这个结果,而使用指针取b的地址,所以是可以通过指针来修改对应的值。
这个和指针类似,并且必须在开头初始化,此刻我不禁想到 int * const ,因为在C++中,const修饰的就是真正意义上的常量,这也必须在开始定义时候进行初始化。
例如我们来做一个对比:

在这里插入图片描述

我们看一下这部分代码,我们可以看到第一行,编译器已经提示出错,必须要初始化,第二行就是给指针类似 int &re = a; 这个过程,第三句想修改该指针的指向,但是发现无法修改,编译器已经报错了,类似于 re = b ,该语句我们开始也是想引用变量re换为变量b,但是发现这是一个普通的赋值功能,类似于第四句。
所以我们也知道引用其实也是占用空间的!
所以对于引用,如果想去探究,可以将其当成int * const指针来研究,但是在实际中就没必要,我们只需要知道引用的使用即可。

1.3、作为函数的返回值

作为返回值也需要注意
当返回值是局部变量时:

#include <iostream>

using namespace std;

int& my_max(int a, int b)
{
	int temp;

	if (a <= b){
		temp = b;
	}
	else {
		temp = a;
	}

	return temp;
}

int main(void)
{

	int a = 0;
	int &re = a;

	re = my_max(10,37);

	cout << "re = " << re << endl;

	return 0;
}

运行结果:
在这里插入图片描述
我们发现,这也是可以达到我们想要的结果,因为局部变量temp是在 re = my_max(10,37); 这个语句运行完才会被出栈释放,而返回temp的引用也就是可以有效的赋值给re这个引用。
但是我们考虑到如果在引用初始化的时候让他等于局部变量的引用,是不是会出错,因为在运行完那个语句之后,局部变量就会被释放,那么此刻引用所对应的就不是原来的值了。

#include <iostream>

using namespace std;

int& my_max(int a, int b)
{
	int temp;

	if (a <= b){
		temp = b;
	}
	else {
		temp = a;
	}

	return temp;
}

int main(void)
{

	int a = 0;
	int &re = a;
	int &re1 = my_max(56, 98);

	re = my_max(10,37);

	cout << "re = " << re << endl;

	cout << "re1 = " << re1 << endl;

	return 0;
}

运行结果:
在这里插入图片描述
结果显示re1是一个非法数值,所以在引用作为返回值时,如果返回的是局部变量,一定要注意不要再初始化进行给引用赋值。

当返回值是全局或者static变量时:
其实刚才在上面讨论过后,在这里哪怕不写代码验证,我们都知道完全是可以没问题进行使用的。

1.4、指针引用

在说明之前,我们先写一段代码

#include <iostream>

using namespace std;

struct student_struct{
	int id;
	char name[255];
};

int student_init(struct student_struct **pst)
{
	struct student_struct *petmp ;

	petmp = (struct student_struct *)malloc(sizeof(struct student_struct));
	if (petmp == NULL){
		cout << "malloc err" << endl;
		return -1;
	}

	petmp->id = 10;
	memset(petmp->name,0x00,255);
	memcpy(petmp->name,"gale",4);

	*pst = petmp;

	return 0;
}

void student_free(struct student_struct **pst)
{
	if (*pst == NULL){
		return;
	}
	else{
		free(*pst);
		*pst = NULL;
	}
}

int main(void)
{

	int a = 0;
	int &re = a;

	struct student_struct *pst;

	student_init(&pst);

	cout << "id = " << pst->id << " name:" << pst->name << endl;

	student_free(&pst);

	return 0;
}

运行结果:
在这里插入图片描述

这段代码主要实现一个功能,就是对于学生信息管理的初始化,采用的是申请内存的方式,在这里的话,运用指针的指针,可能会有些绕,导致在写代码的时候容易出错,那么我们能不能用指针引用来处理简化呢?
答案是肯定的整形能够使用引用,那么指针肯定也可以使用,我们使用引用写这部分代码如下:

#include <iostream>

using namespace std;

struct student_struct{
	int id;
	char name[255];
};

int student_init(struct student_struct* &pst)
{
	pst = (struct student_struct*)malloc(sizeof(struct student_struct));

	if (pst == NULL){
		printf("malloc err\r\n");
		return -1;
	}

	pst->id = 10;
	
	memset(pst->name,0x00,255);
	memcpy(pst->name,"gale",4);

	return 0;
}

void student_free(struct student_struct* &pst)
{
	if (pst == NULL){
		return;
	}
	else{
		free(pst);
		pst = NULL;
	}
}

int main(void)
{


	struct student_struct *pst;

	struct student_struct* &student_re = pst;

	student_init(student_re);

	cout << "id = " << student_re->id << " name:" << student_re->name << endl;

	student_free(student_re);

	return 0;
}

运行结果:
在这里插入图片描述

使用指针引用也可以达到目前的功能,但是看这部分代码,你会发现使用指针的引用方式看起来简单很多,如果在之前使用指针的指针,如果一不小心少了个*,那么调试起来会有点耗时,但是使用指针引用后,发现就变的很简单了。
当然不是说一定要使用指针引用,因人而异,喜欢使用什么方式就用什么方式,毕竟代码只是实现某个功能而已。

发布了29 篇原创文章 · 获赞 0 · 访问量 424

猜你喜欢

转载自blog.csdn.net/weixin_42547950/article/details/104302623