目录
引用
1.认识什么是引用
在小学的时候,我们经常给其他同学起外号,像脖子比较长的同学,我们会给那个同学取名“长颈鹿”,“长颈鹿”就是这位同学的别名,引用也可以这样理解,在语法层面上,引用就是取别名。
2.认识“&”符号
在我们学习编程语言时,&符号有多种含义
int c = a & b; //转化为二进制进行与运算
int* p = &a; //取地址
int& j=a //引用
3.引用的定义
引用不是新开辟一个空间去定义一个变量,是给一个已知的变量取别名,编译器不会给引用变量开辟空间,初始变量和引用变量共用一块空间
int a = 0;
int& b = a;
int c = a;
c++;
cout << c << " " << a << endl;
b++;
cout << b << " " << a << endl;
如上,b是a的别名,我们上面也提到了,a和b是共用同一块空间,是不是b++的同时,a也跟着++呢?很显然 输出结果如下:
4.引用的特点
1.引用必须初始化
2.引用不能给空指针
3.一个变量可以有多个引用
4.引用没有二级引用
5.引用的意义
像以前我们写一个Swap交换函数如下
void swap(int* p1, int* p2)
{
int* tmp = p1;
p1 = p2;
p2 = tmp;
}
int main()
{
int a = 2, b = 1;
swap(&a, &b);
return 0;
}
这样写的很繁琐,要取地址,在swap函数还要用指针,当我们学了引用,我们可以简便快捷的写一个Swap函数,如下:
void swap(int& x1, int& x2)
{
int tmp = x1;
x1 = x2;
x2 = tmp;
}
int main()
{
int a = 1;
int b = 2;
swap(a, b);
cout << a << " " << b;
return 0;
}
x1,x2分别是a和b的别名,改变x1,x2相当于改变a和b的值!
所以引用本身是一个变量,但是这个变量又仅仅是另外一个变量一个别名,它不占用内存空间,它不是指针哦!仅仅是一个别名
传引用返回
在认识传引用返回之前,我们复习一下我们已经学习的传值返回
传值返回:生成一个返回对象拷贝作为函数调用返回值
传引用返回,顾名思义,就是在返回值后面加&,如下的int&
int& count()
{
int n = 0;
n++;
return n;
}
int main()
{
int ret = count();
cout << ret << endl;
return 0;
}
ret发生越界了,却仍正常输出值,但这属于侥幸
返回值取得是n的别名(即tmp),而tmp空间上的值就是n原来的数,但这是侥幸,如果有的编译器销毁后n被置成随机值,tmp就会取到随机值
越界:好比申请房间,里面存一个变量,理论上除非别人非法入侵,变量是不会被修改的。但你把房间退了,里面还留着你的东西,就无法保障它不丢失,即使你下回去房间还没租给别人,所以东西被你找到了,也只能说是侥幸(因为换一个房间/编译器,是否还能保证找到就不好说了)
如果是调用第二次就不一样了‘
第一次输出的时候,n销毁了,第二次输出时,已经寻找不到了,输出随机值
总结传引用传参和传引用返回
如果函数返回时,除了函数的作用域,如果返回对象还在,则可以使用传引用返回,如果该对象已经还给系统了,则必须使用传值返回
传引用传参(任何时候都可以)
1.能提高效率
2.改变了形参会影响实参
传引用返回(出了函数作用域对象还在可以使用)
1.提高效率
2.修改返回对象
权限的放大和缩小
1.权限可以平移
2.可以缩小
3.不能放大
权限的放大
const int a = 0;
int& b = a;
这里无法编译通过,定义a是常量,定义b为a的引用时,这是权限的放大,我们应该更改为
const int a = 0;
const int& b = a;
这样我们更改了 这是权限的平移,可以编译通过
权限的缩小
int x = 0;
const int& c = x;
当我们遇到这种情况时
int fun()
{
int a = 0;
return a;
}
int main()
{
int& ret = fun();
return 0;
}
这样是编译不通过的,因为传值返回时,会产生一个临时变量,临时变量具有常性,定义引用的时候是int, 这是权限的放大,所以我们应该加一个const
int fun()
{
int a = 0;
return a;
}
int main()
{
const int& ret = fun();
return 0;
}
引用和指针的区别
使用场景:
指针和引用用途基本是相似的(能用指针的地方基本能用引用,能用引用的地方也基本能用指针),它们一般都是用于做一些参数、返回值的地方,它们有提高效率、做输出型参数返回对象这样的,但一般这些场景引用更合适的。
指针有引用替代不了的地方:如C++中这种链表、链式结构的场景,引用无法替代。
a.引用必须在定义的时候初始化(指针可以初始化,也可以不初始化)
b.引用指向一个实体后,就不能再引用其他实体
指针更强大,更危险,更复杂;引用相对局限一些,更安全,更简单
最后总结
1.引用概念上定义一个变量的别名,指针存储一个变量地址
2.引用在定义时必须初始化,指针没有要求(指针不初始化其值为随机指向)
3.引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体
4.没有NULL引用,但有NULL指针
5.空指针没有任何指向,删除无害,引用是别名,删除引用就删除真实对象
6.在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)
7.引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
8.有多级指针,但是没有多级引用
9.访问实体方式不同,指针需要显式解引用,引用编译器自己处理
10.引用比指针使用起来相对更安全
11.指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作。程序中使用指针,程序的可读性差;而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作
本文部分采用如下链接的原文
原文链接:https://blog.csdn.net/SHIE_Ww/article/details/126580559
以下就是本篇的全部内容啦!感谢大家观看!