欢迎来CILMY23的博客
本篇主题为 掌握C++函数重载和引用开启代码优化的新篇章
个人主页:CILMY23-CSDN博客
个人专栏: | | | CILMY23-CSDN博客
上一篇博客:第一个C++结构,C++关键字,命名空间,C++的输入输出,缺省参数
感谢观看,支持的可以给个一键三连,点赞关注+收藏。
目录
一、 函数重载
1.1 函数重载的概念
1.2 cpp是如何支持重载的呢?
1.3 Linux -- gcc 编译器下的规则
1.4 Visual Studio 2019 的命名规则
二、 引用
2.1 引用概念
2.2 引用的用法
2.3 引用的特点
2.4 引用的应用1 --- 做参数
2.5 引用不能代替指针的原因
2.6 引用的应用2 --- 做返回值
2.7 引用和指针的区别
2.8 引用和指针的不同
本文前言
上一篇简要介绍了C++编程语言的初级概念。我们学习了C++的程序结构和基本语法,了解了关键字的作用和用法。通过命名空间,我们可以避免命名冲突,并组织代码。使用cin和cout进行输入输出操作,方便与用户交互。缺省参数可以使函数调用更灵活。通过学习,我们打下了C++编程的基础。接下来,我们将继续学习重点知识 --- 函数重载
一、 函数重载
在过去我们学习C语言的时候通常都会碰到一个问题,我们定义函数的时候是不让同名的,也就是ADD函数只有一个,所以我们为了方便起见通常用一个宏来定义一个type,这样方便修改函数的数据类型,而在C++中,我们引入了函数重载的概念,它允许函数同名,但要求参数不同
1.1 函数重载的概念
函数重载是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数或类型或类型顺序)不同,常用来处理实现功能类似数据类型不同的问题
函数重载一共有三种方式:
1.函数参数的数据类型不同
2.函数参数的顺序不同
3.函数参数的个数不同
//函数重载
//1.函数参数的数据类型不同
int Add(int a, int b)
{cout << "this is int Add" << endl;return a + b;
}double Add(double a, double b)
{cout << "this is double Add" << endl;return a + b;
}
//2.函数参数的顺序不同
void A(int a, char b)
{cout << "void A(int a, char b)" << endl;
}void A(char b, int a)
{cout << "void A(char b, int a)" << endl;
}
//3.函数参数的个数不同
void f()
{cout << "void f()" << endl;
}void f(int a)
{cout << "void f(int a)" << endl;
}
注意:函数重载不能依靠返回值的不同来构成重载,因为调用时无法根据参数列表确定调用哪个重载函数
例如:double Add() 和int Add()不能构成重载函数。
1.2 cpp是如何支持重载的呢?
在C语言中,我们的C是直接通过函数名去找地址的,所以它不支持重载的原因是同名函数不知道该找谁的地址。
那我们知道从编译到可执行程序需要经历四个阶段,预编译,编译,汇编,链接(第一个C++结构,C++关键字,命名空间,C++的输入输出,缺省参数)
那C++是如何支持的呢?我们引入了一个规则 --- 函数名修饰规则, 我们不是要通过函数名来查找函数地址吗,那如果函数名的修饰再加上参数以及其他的一些符号,这样通过不同函数名和不同的参数就能确定一个唯一的地址。
但是并没有很强制的规定,所以各个编译器都自己实现了一套命名规则。
1.3 Linux -- gcc 编译器下的规则
在gcc当中,它们的命名方式比较简约。
_Z + 函数名称长度 + 函数名称 + 参数类型首字母
1.4 Visual Studio 2019 的命名规则
当我们声明和定义分离的时候,把定义部分去掉,就可以在Visual 的窗口中看到报错
当我们写很多种的函数就可以总结一个规律
visual 的修饰 (?+ 函数名称 + @@YA + 参数类型 + @Z)
二、 引用
2.1 引用概念
引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空 间,它和它引用的变量共用同一块内存空间。
2.2 引用的用法
引用的语法如下:
类型& 对象名 = 引用实体
例如:
//引用int main()
{int a = 0;int& b = a;int& c = b;cout << b << endl;a++;cout << b << endl;b++;cout << c << endl;}
结果:输出0,1,2
b 就是 a ,别名是可以无限取的,就跟人的名字一样,有无数外号,别名也可以有别名。
注意:引用类型必须和引用实体是同种类型的
2.3 引用的特点
1. 引用在定义时必须初始化
2. 一个变量可以有多个引用
3. 引用一旦引用一个实体,再不能引用其他实体
错误1:
int a = 10;
int& ref; // 无法通过编译,因为ref没有进行初始化
错误2:
int a = 10;
int b = 20;
int& ref = a; // ref现在引用a
int& rref = a;
2.4 引用的应用1 --- 做参数
过去我们在C语言中,要交换两个变量的值,通常用函数+指针+额外变量来进行交换,现在我们可以用引用来处理。
//引用特点 --- 做函数参数
void Swap(int* a, int* b)
{int tmp = *a;*a = *b;*b = tmp;
}void Swap(int& a, int& b)
{int tmp = a;a = b;b = tmp;
}int main()
{int n1 = 10;int n2 = 20;Swap(n1, n2);
}
Swap函数使用的是引用参数,对a和b的操作会直接影响到n1,n2,不需要额外开辟空间。
参数也分两种(a.输出型参数b.是对象比较大,减少拷贝提高效率)
2.5 引用不能代替指针的原因
指针和引用的功能有部分是类似的,有些复杂场景是可以替代的,但是不能完全替代指针。
引用不能完全替代指针的原因:引用定义后,不能改变指向
2.6 引用的应用2 --- 做返回值
我们在调用函数的时候,出了函数作用域的东西,就可能会出现随机值,
int fun1()
{int a = 0;return a;
}int main()
{int ret = fun1();return 0;
}
传值返回的函数,ret就是读取不到a,函数会临时拷贝a的值存在寄存器中然后将a的值返回。
但函数也可以传引用,像以下情况就不行
int& fun1()
{int a = 0;return a;
}int main()
{int ret = fun1();cout << ret << endl;return 0;
}
但是这里会报错,,这里栈帧没清,所以值是0,也因此值在不同平台是不同的,
如果函数返回时,出了函数作用域,如果返回对象还在(还没还给系统),则可以使用引用返回,例如:全局变量,静态变量,堆上变量等,如果已经还给系统了,例如:局部变量,则必须使用传值返回。
2.7 引用和指针的区别
在语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间。在底层实现上实际是有空间的,因为引用是按照指针方式来实现的。
int main()
{int a = 10;int& ra = a;ra = 20;int* pa = &a;*pa = 20;return 0;
}
汇编代码的对比:
引用和指针的效率对比:
#include <time.h>
struct A { int a[10000]; };
A a;
// 值返回
A TestFunc1() { return a; }
// 引用返回
A& TestFunc2() { return a; }
void TestReturnByRefOrValue()
{// 以值作为函数的返回值类型size_t begin1 = clock();for (size_t i = 0; i < 100000; ++i)TestFunc1();size_t end1 = clock();// 以引用作为函数的返回值类型size_t begin2 = clock();for (size_t i = 0; i < 100000; ++i)TestFunc2();size_t end2 = clock();// 计算两个函数运算完成之后的时间cout << "TestFunc1 time:" << end1 - begin1 << endl; cout << "TestFunc2 time:" << end2 - begin2 << endl;
}
结果如下;
2.8 引用和指针的不同
1.引用概念上定义一个变量的别名,指针存储一个变量地址。
2.引用在定义时必须初始化,指针没有要求
3.引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何
个同类型实体
4.没有NULL引用,但有NULL指针
5.在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)
6.引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
7.有多级指针,但是没有多级引用
8.访问实体方式不同,指针需要显式解引用,引用编译器自己处理
9.引用比指针使用起来相对更安全
感谢各位同伴的支持,本期C++入门篇就讲解到这啦,如果你觉得写的不错的话,可以给个一键三连,点赞关注+收藏,若有不足,欢迎各位在评论区讨论。