文章目录
- 🚀前言
- 🚀函数重载
-
- 注意:
- ✈️为什么C++可以实现函数重载,而C语言却不行呢?
- 🚀引用
-
- ✈️引用的特性
- ✈️C++中为什么要引入引用
- ✈️引用与指针的区别
- 🚀内联函数
-
- ✈️内联函数特性
🚀前言
大家好啊!好久没更文了,课多还有就是备战前几天考完的蓝桥杯,好了不多bb,接着带大家从C语言过度到C++!!!
🚀函数重载
当年本贾尼,本大爷在编C++的时候觉得C语言中的函数不够方便,于是就整了个函数重载
函数重载:在C++中,允许同一作用域声明几个功能类似的同名函数,这些函数具有相同的函数名,但具有不同的参数列表(形参数不同、类型不同 以及类型顺序不同)常用来处理实现功能类似数据类型不同的问题。
实话说,干巴巴的文字没一点意思,还是给铁子们来点🌰:
int Add(int left, int right)
{
cout << "int Add(int left, int right)" << endl;
return left + right;
}
double Add(double left, double right)
{
cout << "double Add(double left, double right)" << endl;
return left + right;
}
int main()
{
Add(10, 20);
Add(10.1, 20.2);
return 0;
}
运行输出:
int Add(int left, int right)
double Add(double left, double right)
上面这两个个add函数如果用C语言编写还不得整个add_int和add_double啊,这多麻烦,C++的函数重载简直不要太爽
void f(int a){
cout<<"void f(int a)"<<endl;
}
void f(int a,int b){
cout<<"void f(int a,int b)"<<endl;
}
int main(){
f(1);
f(2,3);
return 0;
}
运行输出:
void f(int a)
void f(int a,int b)
void f(int a,double b){
cout<<"void f(int a,double b)"<<endl;
}
void f(double a,int b){
cout<<"void f(double a,int b)"<<endl;
}
int main(){
f(1,2.0);
f(1.0,2);
return 0;
}
运行输出:
void f(int a,double b)
void f(double a,int b)
注意:
函数的返回类型不同并不构成函数重载 也就是:
void add(int a,int b){....}
int add(int a,int b){return 0}
上面的add函数并不构成重载
为什么呢?我们接着往下看⬇️
✈️为什么C++可以实现函数重载,而C语言却不行呢?
这就与编译器有关了,一般C/C++的程序运行起来可以分为两个大的过程——编译和链接,在程序编译过程中会将每一个函数解析成唯一的标识符,然后将函数标识符及其地址编成符号表(符号表,我们可以简单把它理解成是一张维护标识符(变量、常量、函数)以及其相关信息的映射表),而后的链接过程中遇到一个函数调用时,就会通过该函数的标识符在符号表中找到对应的函数地址并与函数调用关联起来。
而C++可以实现实现重载,C却不能,主要是因为函数在编译过程解析成标识符这一步不同 比如:
void add(int a,int b){}
上面的函数在C编译器上一般会被编译类似 add 这样的标识符
而在C++中则会编译成类似 addii 这种标识符,后面的两个i表示该函数有两个int类型的形参
就是因为C语言在处理函数标识符时只与函数名有关,而一旦函数名相同就造成函数重定义,所以就注定C语言无法构成重载,而C/C++对于函数标识符的处理都与返回值无关所以返回值不同无法构成重载
🚀引用
引用:语法层面上就是已定义变量的别名,与该变量共用一块内存空间 栗子🌰: 类型& 引用变量名(对象名) = 引用实体 引用的类型与被引用的变量类型一致
int a = 10;
int& b = a;
b = 5;
b 对于a的关系 就相当于你的名字和小名以及外号的关系 都指的是你
对b进行修改其实就相当于改了a
其实不妨这么理解,定义a就相当于想系统申请了一块空间名字是a,而引用b则是给这块空间又起了一个名字,如果再次int& c = b就相当于这块空间又有了一个名字c,对a,b,c操作实际上都是对这块空间操作,所以a,b,c的值都会更改
✈️引用的特性
- 引用必须初始化: 这很好理解,引用就是所定义变量的别名,如果不初始化那么引用就没有所代表的内存空间
int main(){
int& a;
return 0;
}
不初始化就会报错
- 引用一旦引用实体后,就不能引用别的变量了
int main()
{
int a = 5;
int c = 1;
int& b=a;
b = c;//这样b就是c的别名了吗?
cout << a << " " << b << " " << c << endl;
return 0;
}
运行输出:
1 1 1
其中b = c并非是b成了c的引用,而是将c的值赋给b,而b是a的引用,b改了,a也就改了
✈️C++中为什么要引入引用
C/C++都是追求效率的语言,而C++中引入的引用其实就是代替了C中指针的大部分职能,比如在函数传参过程中如果是传值调用,这样就会出现拷贝,这极大的降低了效率,而C语言中通常会通过指针使用传址调用提高效率,而C++中则可以使用传引用做到与C中指针的传址调用同样的效果,甚至更便捷、安全。
栗子🌰:
//通过传引用交换变量
void swap(int& a,int& b){
int tmp = a;
a = b;
b = tmp;
}
int main(){
int a = 0,b = 4;
swap(a,b);
return 0;
}
注意⚠️:引用可以作为函数的返回值,一旦引用对象的生命周期只在函数内则会造成,返回的引用属于悬空引用,即引用指向的空间已销毁
✈️引用与指针的区别
大家应该应该注意到上文对于引用,我只说引用在语法上是已定义变量的别名,与该变量共用一块内存空间,其实在底层实现上引用本质就是指针
注意: 引用只能完成指针较为简单的部分,但是不能替代指针!!
🚀内联函数
内联函数其实是本大爷为了解决C中那让人恶心的宏函数而设计出来的
宏缺点:
1、不能调试(预处理阶段宏就被处理了) 2、没有类型安全的检查 3、有些场景下非常复杂,容易出错,不容易掌握
内联函数:以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调用建立栈帧的开销,内联函数提升程序运行的效率 栗子🌰:
inline int add(int a,int b){
return a + b;
}
int main(){
int a = add(1,2);
return 0;
}
✈️内联函数特性
缺陷:由于是在调用处展开,则代码量将会扩大,也就导致目标文件的增大. 优势:少了调用开辟函数栈帧的开销,提高程序运行效率
//定义和声明在一块
inline int add(int a,int b){
return a + b;
}
今天的分享到这里就结束啦!如果觉得文章还不错的话,可以三连支持一下,您的支持就是阿辉前进的动力!
评论前必须登录!
注册