各位小伙伴们,大家好。今天俺依然来给大家介绍一下C++入门,今天我们讲的内容是:函数重载、引用和内联函数,希望大家通过这篇文章的学习,可以对这几个知识点有更全面的认识,话不多说,让我们进入这场没有硝烟的战争吧!
目录
一、函数重载:
1.概念:
函数重载就是允许在同一个作用域中实定义函数名相同的函数(天下并没有无规则的创建,这个功能同样是有限制的,下面会说)
2.使用规则:
在函数名相同的前提下,函数的 参数类型、参数个数 不同(二者选一即可)
3.现场演示:
函数名、参数个数相同,但是参数类型不同,依然可以正常运行
函数名、参数类型相同,但是参数个数不同,可以运行
4.原理:(知其然知其所以然)
一个可执行文件的生成是需要经历 编译、预处理、汇编、链接 4个阶段,那么,在一个文件编译后链接前,就会将目标文件调用的函数与函数地址链接起来,问题就在这里,编译器是通过什么方法去查找函数呢?或者说,编译器的命名方法是什么呢?由于windows下的使用规则过于复杂,因此,我们在Linux下进行讲解( 查询编译后的代码指令 -- objdump -S 可执行文件 ):
①使用 C 进行编译生成可执行文件的命名方法( gcc -o ....):
无变化
②使用 C++ 进行编译生成可执行文件的命名方法( g++ -o ....):
有变化
当然,我这里就不给大家展示相同函数名的代码指令了,因为C++的命名规则不仅包括函数名,还包括函数参数,上图所示的 Z4funcii 和 Z5func1cc,代表的是(Z不谈):func/func1(函数名)、ii/cc(函数参数类型),因此,C++的语言规则中,函数名可以相同,因为决定名称的还有参数类型和参数个数,所以,这也可以证明另一件事:函数的返回类型并不属于命名范围。因此,大家在考虑重载函数时并不能把函数的返回类型考虑进去。
二、引用:
1.概念:
引用并不是定义一个新的变量,而是对一个已存在变量取一个“别名”,他们都使用同一块空间(语法上可以这么理解,实际上还是有所区别),就像龙珠里的 “孙悟空” - “狗空” - “卡卡罗特”
2.用法:
类型& 名称 = 引用实体 (引用实体必须和引用变量名是同一种类型!!!!)
int main()
{
int a = 5;
int& ret = a; // ret 为 a 的别名
cout << a << endl;
cout << ret << endl;
return 0;
}
3.特性:
①引用在定义时必须要初始化
②一个变量可以有多个引用(可以有多个别名:“狗空”、卡卡罗特“、”孙悟空”)
③同一个引用变量名不可以对多个变量引用(“卡卡罗特”只能是悟空,不能是悟饭)
④引用只能对变量引用!!!常量不可以!!!
4.典型反面教材:
①对被const修饰的变量引用:
int main()
{
const int a = 5;
// int& ret = a; //报错,因为被const修饰的变量具有常属性,而常量不能被引用
const int& ret = a; //正确,傀儡的权限不能放大
cout << a << endl;
cout << ret << endl;
return 0;
}
②变量被强制类型转换后的引用:
int main()
{
double a = 5.0;
int& ret = (int)a; //报错
cout << a << endl;
cout << ret << endl;
return 0;
}
a 是 double 类型的变量,要对 a 取一个 int 类型的别名,所以将 a 强制转换为 int 类型,可是为何还是会报错呢?答:因为在对a进行强制类型转换时,将 a 的值强制转换成 int 类型的值(常量)存放在一个临时开辟的空间中,不可以对常量进行引用,所以这个代码是错误的
5.其他使用场景:
①做参数:(傻子都会,略)
②做返回值:
int& Count()
{
static int n = 0; //静态区开辟的变量
n++;
// ...
return n;
}
③分析这个代码的运行过程:
第1次调用时,为函数开辟一个栈空间,存放参数 a 和 b 的值以及 临时变量 c ,运算后 c 为 3,然后返回 c 的值,函数运行结束,空间返还给操作系统,ret 引用函数 Add函数返回值,实际上引用的是已经释放的空间,第2次同理,所以最后运行的结果是 7
*** 值得要注意的是,函数在调用时会创建一个函数栈帧用来存储 形参、临时变量等,在函数调用完毕后栈帧会销毁,空间会返还给操作系统,但是返回给操作系统的空间存储的值并不一定会发生改变,所以我们在使用时要注意观察变量的生命周期
*** 一般情况下,函数返回时若出了作用域返回对象还存在,就可以使用引用返回。若出了作用域返还对象不存在,则使用传值返回
6.传值与引用 效率相比较:
很显然,引用作为参数效率比值作为参数快很多倍,返回类型同理
7.引用与指针:
有那么一瞬间,我会觉得引用好像指针哇,但其实二者有相似之处,也有诸多不同之处:
①引用是一个变量的别名,而指针是存储一个变量的地址
②引用在定义时必须初始化,而指针不用
③引用在引用了一个实体后就不能再对其他实体进行引用(专一),而指针可以随时更换指向的地址
④没有NULL的引用,但是有NULL指针
⑤引用对象大小为引用实体类型的大小,而指针大小始终为4个字节
⑥运用对象自增1后,引用实体也会自增1,而指针自增1后会向后偏移1个类型的大小
⑦无多级引用,但是有多级指针
⑧结合上述特点可以得出:引用比指针更安全
三、内联函数:
内联函数就是以 inline 修饰的函数,在编译时C++编译器会在调用内联函数的地方展开,也就不会有函数调用建立栈帧的开销,也就可以提升运行效率(空间换时间)
*** 特性:
①在编译阶段会用函数体替代函数的调用,缺点是:会使目标文件变大,优点是:提高运行效率
②inline只是对编译器的一个建议,不同的编译器对于inline实现的机制也不同。一般情况下:将函数规模较小、非递归、不是频繁调用的函数作为内联函数(内联只是向编译器发送一个请求,编译器可以忽略这个请求)
③inline不建议声明和定义分离,分离会导致链接错误
以上就是版本篇文章的全部内容了,感谢小伙伴们的阅读!!!希望我们都有一个美好的未来!