【C++】函数引用和重载

一、引用

1.引用概念:

引用(reference)就是C++对C语言的重要扩充。引用就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样。引用的声明方法:类型标识符 &引用名=目标变量名。   我让林冲去招安和我让豹子头去招安的意思一样。

注意: 用并没有开辟额外的空间,造成比必要的空间浪费。

1.1引用要求

  • 引用在定义时必须初始化,且初始化指定后就不可修改,指针不必初始化,但可以改变指向
  • 一个变量可以有多个引用。
  • 引用一旦引用一个实体,再不能引用其他实体

引用的具体运用:

int main()
{
	int a = 10;
	// int& b;  // 1、引用在定义时必须初始化
               //此时b就是a的小名

	int& b = a; // 2、一个变量可以有多个引用
	int& c = a;
	int& d = c; // 也可以给别名取别名
    // 3、引用一旦引用一个实体,再不能引用其他实体,d不能在引用其他变量。
	++a;

	int x = 10;
	
	b = x; // b是x的别名呢?还是x赋值给b呢?-->是赋值而非别名(调试看地址和原先别名的a是一样的,这和指针不同)

	return 0;
}

 

2.引用的真正场景

  • 1)做参数
    • ①输出型参数–>指针也能做,但引用相对舒服点。
    • ②大对象传参,提高效率–>没有拷贝,引用不开空间。
  • 2)做返回值
    • ①输出型返回对象,调用者可以修改返回对象。
    • ②减少拷贝,提高效率。

2.1做参数

做参数时和指针的应用有很大相似性。

引用一般用作输出型参数

 这里的引用和指针作用基本一致,都能找到地址来改变数据。但是tmp为啥不用指针呢?因为a, b都不是地址,而是用的别名,但是也不是地址。

2.2做返回值

引用用作返回值是有条件的。当函数执行完作用后如果没有被销毁,那他可以用引用,如果被销毁了,就不能用作返回值了。因为当函数被销毁后地址就没了,而引用是一个别名,地址不变,但现在地址都没了还咋用。

#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>  
#include <limits>

using namespace std;

int temp;
int func1()
{
    temp = 5;
    return temp;
}

int& func2()
{
    temp = 8;
    return temp;
}

int main()
{
    int a = 0, b = 0;
    // 1. 返回函数的普通类型
    a = func1();
    // 2. 返回函数的引用
    b = func2();
    // 3. 返回函数的引用去初始化一个新的引用
    int& c = func2();

    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    cout << "c = " << c << endl;

    return 0;
}

注意:一般传值引用是输入型参数,传址调用可以是输出型参数,也可以做输入型参数,做输入型参数时前面加const,表示只读不改。

2.3传值返回和传引用返回

2.31.传值返回:生成一个返回对象拷贝作为函数调用返回值。

传值返回跟传值传参的情况很一致,它只是一份临时拷贝,不能修改本质。

2.32传引用返回: 返回对象(n)的别名 

传引用返回的正确运用:

这个代码正确吗?为啥结果是对的?

  •  假如返回值取得是n的别名(即tmp),而tmp空间上的值就是n原来的数,
  • 但是出了Count函数,tmp就被销毁了,之所以还能打印出正确结果是侥幸,如果有的编译器销毁后n被置成随机值,tmp就会取到随机值。
  • 越界:好比申请房间,里面存一个变量,理论上除非别人非法入侵,变量是不会被修改的。但你把房间退了,里面还留着你的东西,就无法保障它不丢失,即使你下回去房间还没租给别人,所以东西被你找到了,也只能说是侥幸(因为换一个房间/编译器,是否还能保证找到就不好说了)。

 要想使用传引用返回就必须保证:返回值的别名出了作用域而未被销毁,还可以用作返回值。否则,这个别名并未改变它“本名”的地址,当原来的地址被销毁后,再去访问其地址也是胡闹。第一次可能闯上了,但第二次就一定不是了,不信看代码。

printf也属一个函数调用,也需要建立栈帧,

栈帧的大小不一样,第一次可能没有覆盖Count的栈帧,但是第二次可能就覆盖了,所以打印的是随机值。

理解:第一次printf调用后,就被销毁了n,第二次printf再回去找就找失败了。

注意:不要弄混了传值,传址的区别;传值,传引用的区别。

2.33.总结传值返回和传引用返回:

  • 出了函数作用域,返回对象就销毁了,那么一定不能用引用返回,一定要用传值返回
  • 下面的这个场景(static),出了作用域变量还在,才能使用引用返回

3.权限的放大和缩小

3.1权限的放大

 权限只能平移和缩小而不能放大。

3.2权限的缩小

 3.3类型转换

 大家看这段代码,为啥rdd必须加const修饰呢?

ii是int类型,rdd是double类型,当引用时会发生类型转换,但是ii还是int类型,只不过转换途中会产生一个临时变量。而rdd是这个临时变量的别名而临时变量具有常性,相当于const修饰过所以为了权限平移,加const。

3.4const引用传参

权限的放大和缩小只针对引用和指针,对于普通函数,根本没这个概念。

  •  对于这个函数,把a拷贝给n,n的改变不会影响a。

但是我们要是用引用传参

 b,30根本传不过去,因为n是a的别名,又把b传过去,n改变了,所以a就改变了,所以会报错。

所以如果使用引用传参,函数内如果不改变n,那么建议尽量用const引用传参

 3.5传引用返回和传引用传参

  • 传引用传参

引用参数则是把形式参数转换成实参,换句话说就是在函数体里面实际操作的是参数的本身,即存放变量值的内存。

  • 传值传参

当传入的是普通参数时,实际上函数体做了一个偷天换日的动作,是把普通参数的值,复制到有函数体生成的一个内存中。所以,在函数体中参数的值和传入时的值是一样的,但是它们内存地址是不一样的。

  • 传引用返回

返回引用类型和传入引用参数类似,返回的值就是实际中函数体所操作的内存,所以,如果返回类型为引用时,不能将函数体中的局部变量返回(一般返回静态常量)局部变量的生命周期在函数体结束,当函数体结束时,局部变量也跟着结束。返回类型为引用时可以作为左值和右值

  • 传值返回

返回普通类型和传入普通类型类似,函数体即将被返回的值也被偷天换日,将准备返回的值放入一个新生成的内存,最后再返回新生成的内存,这样就解决了函数体结束,局部变量也跟着结束的问题。返回类型为普通类型时,只能作为右值(=右边)来使用。

4.指针和引用的区别

  1. 引用概念上定义一个变量的别名,指针存储一个变量地址
  2. 引用在定义时必须初始化,指针没有要求(指针不初始化其值为随机指向)
  3. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体
  4. 没有NULL引用,但有NULL指针
    • 空指针没有任何指向,删除无害,引用是别名,删除引用就删除真实对象
  5. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)
  6. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
  7. 有多级指针,但是没有多级引用
  8. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
  9. 引用比指针使用起来相对更安全
  10. 指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作。程序中使用指针,程序的可读性差;而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作

二、函数重载 

1.什么是函数重载 

函数重载是指在同一作用域内,可以有一组具有相同函数名,不同参数列表的函数,这组函数被称为重载函数。

重载函数通常用来命名一组功能相似的函数,这样做减少了函数名的数量,避免了名字空间的污染,对于程序的可读性有很大的好处。

函数重载的条件:

这些同名函数的形参列表(参数个数 或 类型 或 顺序)必须不同。

  •  例如交换两个数,我们写一个形参是int的,但是传入的值是double型的这个函数就搞不了了,但是C语言不支持同名函数,而C++支持,也就是说把形参的类型转化一下就可以了。

 一定要注意函数重载不是函数重写!参数个数,参数顺序,参数类型至少有一个不同才算重载。

仅仅修改函数的返回值是不构成重载的。

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值