c++中的引用(&)

2023-12-26 06:17:26

引用?

引用是c++中的,在C语言中是无法使用的。?

引用的作用:?

引用可以理解为给变量起一个别名(这时候大家可能会想到typedef,但是它们不同(原因看后面))。起一个别名之后,我们使用变量别名其实就是使用变量自己,生活中,我们会有自己的小名,那么别人使用小名和本名叫你,对于你而言其实都是一样的。

引用的定义:?

int a = 10;

int& nub = a;  // 给a取一个别名 

上面的第二行代码就是给变量a起了一个别名nub ,这里可以看到在起别名的时候,要使用&符号。由于nub是a的别名,所以nub其实就是a(先这么理解),所以使用nub和使用a是一摸一样的。?

注意:? (原因在后面)

?1. 引用是给变量起别名,所以它在定义的时候必须=一个变量(也就是定义一个引用的时候必须初始化为一个变量)?

2. 当一个引用变量作为一个变量的别名之后,那么这个引用变量就不能作为别的变量的别名了。?

? ? 例: 上面代码中nub已经作为a的别名了,? 在执行 int &nub = c; 这是我们再将nub作为c的别名的时候,那么就会报错?

引用作为函数参数:

void swap1(int &a, int &b)  // 作为参数定义时不需要初始化,但是下面定义的时候需要初始化
{
	int temp = a;
	a = b;
	b = temp;
}  

上面的函数就使用引用作为参数。?

当我们调用函数传递实参的时候,那么函数中的a,b就作为传入实参的别名在函数中使用。?

为什么使用引用作为参数(原因在后面)?

原因: 我们使用引用作为实参,也可以实现值传递(函数参数为指针)的效果,函数中对形参的操作会影响到外部的实参。 就像上面swap1函数实现了a,b两数值交换,那么函数内a,b值进行交换那么作为实参的两变量的值也互换了。?

?其实理解这个原因很简单,操作别名和操作本名是一样的,所以在swap1函数内操作别名就行党羽操作传入的实参,所以互换别名的值不久是互换原名的值吗。

函数调用:??

那么我们应该怎么调用函数呢? 和原来的一样。?

int a = 100, b = 10;? ?swap(a,b);??

引用的地址:

?int sc = 10; int &md = sc;? ?我们同时取sc和md的地址,&sc,&md,会发现两个地址是一样的。

引用的本质?

引用的本质:?

现在我们来看一下引用的本质: 我们前面说到过,int &a = b; 就可以将a看作b,对a操作就是对b操作,而且我们打印a和b的地址发现地址竟然一样。我们可能会认为a和b就是一个东西,代表一片内存。

但是,其实引用变量是由自己的内存的,也就是a有自己的内存并不是和b一样。那引用是什么呢??

我们在引用作为函数参数的时候说到过,它也可以实现和指针类似的功能,这是为什么呢??

因为,引用就是指针,对引用就是指针,所以指针有的特性它都有。?

引用作为指针:?

既然引用是指针为什么和指针的定义不一样?

因为,c++编译器在底层给你换掉了。?

引用定义时:?

int &a = b; 还是这个例子:当我们定义一个引用的时候,其实在底层编译器将这段代码转换成了?

int * const a = b; 这不就和指针的定义一样了吗 ?(那为什么由const,后面说,其实你也能想到了)。

引用访问时:?

当我们使用引用时, 是直接 a = 20, printf("%d",a); 在底层编译器将它替换成了.*a = 20;??

printf("%d",*a);?

函数调用时:

函数调用时也是进行了底层的替换,?

void swap1(int &a, int &b)  // 作为参数定义时不需要初始化,但是下面定义的时候需要初始化
{
	int temp = a;
	a = b;
	b = temp;
}  

上面这个参数在底层编译器进行了替换:?

/*执行引用的函数时,在底层会被替换*/
void swap1(int* const _a, int* const _b) // 变量名可能不一样,底层可能换成别的
{
	int temp = *_a;
	*_a = *_b;
	*_b = *_a;
}

其实就是,引用定义和引用访问的替换。 上面说的,编译器替换可能减参数的变量名换一个(变量名并不重要)。?

const的指针:?

前面说到的,引用无法同时作为两个变量的别名,就是因为int *const, *const的指针是无法指向别的地址的,那么自然引用无法同时作为两个变量的别名。

指针的引用:?

引用是给变量取别名,指针也是变量,所以也可以取别名?

int * b = &c;?

int * &a = b;?// 因为变量b是int*类型的,所以定义此类型的别名,自然要使用int*类型来定义。

结合上面的本质: 其实这就是定义了一个双指针。?

为什么使用指针的引用呢??

我们双指针中说到,它可以用在作为函数参数,将函数中的静态变量带出函数,那这里的指针引用也是一样的。?

void demo(int*& a)
{
	static int nub = 10;
	a = &nub;
}

上面的函数就使用了指针引用作为参数了,因为a是int*类型的引用,所以我们在函数中使用a就相当于直接在函数中使用实参,(实参是一个int*的一级指针)?所以用a和用一个一级指针是一样的。

常引用

我们定义的别名,是通过别名修改原名中的值,如swap1中的值互换,我们可以使用const将引用设置成只读,这样我们使用别名只能访问不能改值。?

用变量作为右值?

	/*用变量初始化常引用*/
    int z = 10;
     
	const int& q = z; // 只能访问数据,不能修改数据

就像上面的代码,我们在定义z别名之前加了const,这样q作为z的别名只能访问z中的值,但是无法修改它的值。

用字面量作为右值?(不常见,也不建议用)

?

/*用字面量初始化常引用(2等这种常数)*/
const int &q1 = 10; // 为什么可以呢,编译器会对这样定义的引用去分配内存,相当于一个常量了(其实没啥 
                       用)
                    // 不要这样使用

?看上面的代码,这样使用,编译器就和之前的处理不同了,遇到等于一个字面量的值的常引用,

const int &q1 = 10;这时候编译器会认为,是定义了一个const修饰的int变量,会为它分配空间。对其实我们这样不如直接 const int q1 = 10; 所以方法就不要使用了?

为什么使用引用:?

上面说到,引用就是指针,指针的使用是比较难理解的,所以c++使用引用来使我们更加方便,当我们定义了一个引用之后,我们就认为对这个别名操作就是对原来变量操作。这样就避免使用指针,一些操作是在底层进行了。

所以,我们使用引用就认为它是定义了相应类型值得别名,之后我们使用引用就和使用原变量得方法一致。?

?

?

?

文章来源:https://blog.csdn.net/weixin_68026222/article/details/135210939
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。