栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

引用(C++)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

引用(C++)

  • 1.引用
    • 1.2 引用的定义
    • 1.3 引用的特性
    • 1.4 引用的权限
    • 1.5 引用做参数和返回值
    • 1.6 引用和指针的区别

1.引用

引用并不是定义个新变量,而是给一个变量起一个新的名字,起别名的时候并没有开辟新的空间,而是和原来变量共同使用一块空间;

1.2 引用的定义

类型& 引用变量名(对象名) = 引用实体;

int main()
{
	int a = 0;
	int& b = a;    //b就是a的别名
}

其实可以这样理解(个人),因为&符号是取地址操作符嘛,int& 类型可以当做a不仅将值赋值给了b,地址也给了b,所以他们共用一块空间。

1.3 引用的特性

1:

因为b是a的别名,使用的是同一块空间,所以b的改变会导致a的改变

void test()
{
	int a = 0;
	int& b = a;
	cout << b << endl;
	b = 10;
	cout << b << endl; 
}

2:

引用的时候必须初始化

3:

引用一旦引用了一个实体就不能被改变

void test()
{
	int a = 0;
	int& ra = a;
	int& rra = a;  
	//ra和rra的实体只能是a,不能改变
}
1.4 引用的权限

1:权限对等和放大

const可以使一个变量的权限缩小(能赋值变成不能赋值),如果我取一个常量的别名会怎么样

void test()
{
	int& a = 20;
}

毫无疑问,编译器弹出了一个警告

因为一个常量怎么会有别名呢,如果我加上const呢

void test()
{
	const int& a = 20;
}

这时候编译器就没有报错,因为常量本来就不可以修改,那么我加上const后,a也就不能被修改,所以常量也是可以取别名的,但是权限不能放大;

2:权限缩小:

void test()
{
	int a = 20;
	const int& ra = a;
}

编译器没有报错,说明权限可以缩小

3: 类型转换

void test()
{
	int a = 20;
	
	char& ra = a;//报错
	int& rra = a;//不报错
	double& rra = a;//报错
}

但是,如果我加上const

void test()
{
	int a = 20;
	
	const char& ra = a;
	const int& rra = a;
	const double& rra = a;
}

以上编译器都不会报错

这是因为在引用相同类型的时候,是直接将a进行引用,而在进行不同类型的引用时,会产生类型转换,那么会参生一个临时变量原来储存a转换后的值,再将临时变量赋值给ra,在这时如果取直接引用,那么相当于引用了临时变量,而临时变量具有常性(不可修改),所以会报错,那么加上const后就不会报错。

4:总结

以上结果可以说明,引用的权限可以缩小,但是不能放大,并且引用只能引用同之种类型;

1.5 引用做参数和返回值

1:参数

void test(int& a)
{
	a = 20;
}

int main()
{
	int a = 0;
	test(a);
}

形参a就是实参a的别名,改变了形参a就改变了实参a的值,跟传地址的形式是一样的,但是比传地址好用。

但是如果传常量或者是其他类型的数据就会报错

void test(int& a);

void test2(const int& a);

int main()
{
	char a;
	double b;
	test(20);
	test(a);
	test(b);

	test2(20);
	test2(a);
	test2(b);
}

加上了const就不会报错,道理和上面一样

2:返回值

想想,引用可以作为函数返回值的别名吗

形式一:

int test()
{
	int a = 10;
	return a;
}

int main()
{
	int& a = test();    //报错
	const int& a = test();  //不报错
	return 0;
}

因为返回a的值时,会使用一个寄存器或者是一个临时变量来存储返回值,待test函数被销毁的时候,a的值就会通过寄存器或者是临时变量来做返回值,所以如果直接引用,那么相对于引用了临时变量或者是寄存器,但是它们都是不可改的,所以要加上const才能做引用;

形式二:

int& test()
{
	int b = 10;
	return b;
}

int main()
{
	int& a = test();
	return 0;
}

这其实才是返回值做引用的正确方式,a就是test函数中b的别名,但是还有一些错误,当test函数调用完后空间会被回收,但是a中的地址仍然是test函数中b的地址,但是b的地址已经被系统回收,强行访问会有错误;

形式三:

int& test()
{
	static int b = 10;
	return b;
}

int main()
{
	int& a = test();
	return 0;
}

b的值是全局静态变量,所以b的空间不会随着栈帧销毁被回收,这才是正确的使用方式。

因为b是全局的,那么我第一次得到b的别名后,也可以不用接收返回值
例:

int& add(int a,int b)
{
	static int ret;
	ret = a + b;
	return ret;
}

int main()
{
	int& a = add(10,20);
	cout << a << endl;
	add(30, 40);
	cout << a << endl;
	return 0;
}

结果:

1.6 引用和指针的区别

不同点:

1:引用在定义时没有开辟新的空间,而指针在定义是开辟了空间原来储存地 址
2:引用在定义的时候必须要初始化,而指针不需要
3:有多级指针,但是没有多级引用
4:指针定义后可以被修改,而引用定义后不能被修改
5:访问实体方式不同,指针需要使用解引用操作符访问储存的地址的空间,引用编译器自己处理
6:引用比指针使用起来相对更安全

相同点:
本质是引用和指针是同一个东西,因为引用实现的底层逻辑和指针实现的底层逻辑是一样的,也就是说,其实引用是消耗空间的。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/873199.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号