【C++】C++入门基础知识(二)
【C++】C++入门基础知识(二)
- 一.函数重载
- 1.情景引入
- 2.定义
- 二.引用
- 1.定义
- 2.特性
- 3.使用
- 4.引用和指针的区别
- 三. inline函数(内联函数)
- 1.宏定义引入
- 2.inline函数介绍
- 3.注意事项
一.函数重载
1.情景引入
在C语言中,如果我们要分别实现一个整型加法函数和浮点型加法函数,我们必须定义出两个不同的函数,例如:
//定义整型加法
int Add1(int x, int y)
{
return x + y;
}
//定义浮点型加法
double Add2(double x, double y)
{
return x + y;
}
虽然它们的功能一样,目的也一样,但却要用两个函数来实现,因此C++引入了重载这一新特性解决这种问题。
重载就是 “同一个名字,根据不同情况做不同的事情。”就好比电饭锅的“煮饭”按键,放入大米就是煮大米饭,放入小米就是煮小米粥,放入其他食材能煮出其他食物。
C++的重载包括运算符重载和函数重载,本篇先讲函数重载。
2.定义
C++中同名函数,不同参数可以构成函数重载,包括①参数个数不同、②参数类型不同、③参数个数不同且类型不同。
依旧用加法函数举例,在C++中,只需要一个函数就可以完成不同类型变量的加法。
int Add(int x, int y)
{
return x + y;
}
//参数个数不同
int Add(int x, int y, int z)
{
return x + y + z;
}
//参数类型不同
double Add(double x, double y)
{
return x + y;
}
当调用函数时,编译器会根据参数的不同,自动匹配相对应的函数。

注意,如果函数的参数相同,但返回值不同,这种情况不能构成函数重载,因为传入的参数相同时,编译器不知道该调用哪个函数。
例如:
int Add(int x, int y)
{
return x + y;
}
double Add(int x, int y)
{
return x + y;
}

二.引用
1.定义
引用是C++中的新概念,引用相当于为一个变量起别名。
用法为:
type &变量1=变量2
例如:
int a = 10;
int& b = a; // b是a的别名
对引用的任何操作就是对变量的操作,反之亦然。例如《西游记》中孙悟空有“孙行者”、“斗战胜佛”、“弼马温”等称号,孙悟空西天取经和孙行者西天取经都表示一个行为,引用和变量本身就是指向同一个内存空间。
2.特性
①一个变量可以有多个引用,但引用在创建时必须初始化。


②引用在初始化之后,不能再重新改变指向其指向。
3.使用
引用的主要用途是作为函数的参数和返回值。
函数的传参和返回值的传递方式有三种:值传递、引用传递、指针传递。其中值传递并不能改变实参的值。
例如:
值传递:
//定义一个让参数值加10的函数
//值传递
void Func(int x)
{
x += 10;
}
int main()
{
int a = 1;
Func(a); //调用函数
cout << a; //a的值实际并没有改变
return 0;
}

引用传递:
//引用传递
void Func(int& x)
{
x += 10;
}
int main()
{
int a = 1;
Func(a); //调用函数
cout << a; //a的值发生改变
return 0;
}
运行结果为:

指针传递:
//指针传递
void Func(int* x)
{
*x += 10;
}
int main()
{
int a = 1;
Func(&a); //调用函数
cout << a; //a的值发生改变
return 0;
}

引用传参、作为返回值可以减少拷贝,提高性能和效率。
4.引用和指针的区别
①.语法概念上,引用是另一个变量的别名,不开空间。指针是存储一个变量的地址,要开空间(32位系统下是4个字节,64位系统下是8个字节)。
②.引用在定义时必须初始化。指针语法上建议初始化,但不是必须的。
③.引用在定义完之后不可以修改其指向对象,指针可以。
④.引用可以直接访问对象,指针必须解引用才能访问。
⑤.指针容易出现空指针和野指针的问题,但引用相对比较安全。
引用和指针功能差不多,但使用操作比指针更简单,安全。在拷贝构造函数、范围for循环、函数参数传递(特别是输入参数)等场景下更建议使用引用而非指针。
指针功能强大但较为复杂,因此不当使用十分危险,好比一把锋利的刀,不必要的情况可以减少使用。
三. inline函数(内联函数)
1.宏定义引入
大家在学习C语言应该学习过宏,宏定义就是在编译之前进行文本替换,例如
#include
using namespace std;
#define M 100
int main()
{
int a = M; //预处理后相当于:int a = 100;
cout << a << endl;
}
在预处理时就直接将M替换成100。

宏定义还可用来实现一些简单短小的函数,例如实现一个加法函数:
#define ADD(x,y) x+y
int main()
{
int sum = ADD(1, 2);//预处理后:int sum=1+2;
cout << sum << endl;
return 0;
}
运行结果为:

实际上这个加法函数的写法是错误的,因为宏定义只是进行简单的文本替换,文本替换后可能出现运算符优先级问题等,例如:
#include
using namespace std;
#define ADD(x,y) x+y
int main()
{
int sum = ADD(1, 2) * 3;
//期望的结果是9,但实际上会展开成:sum=1+2*3=7
cout << sum << endl;
return 0;
}
运行结果为:

所以正确写法是#define ADD(x,y) ((x)+(y))

2.inline函数介绍
C语言中的宏函数代码本身不是一种函数,但使用起来像函数,在预处理时,预处理器用复制宏代码替代了函数调用的过程,省去了参数压栈、生成汇编语言CALL调用等,来提高效率,但使用时容易出错,因此C++引入了inline关键字来替代宏定义函数。
将inline关键字与函数定义放在一起就可以构成内联函数。
内联函数是一种编译器优化技术,通过inline关键字建议编译器在代码调用处直接替换成函数体代码,从而减少函数调用造成的开销。
例如上面的加法函数可以写成:
//.h/.cpp文件
#include
using namespace std;
inline int ADD(int x, int y); //声明
inline int ADD(int x, int y) //定义
{
return x + y;
}
相比于宏定义函数,内联函数包含类型检查、按运算符优先级计算等,例如同样计算上述问题时:

因为内联函数是将整体计算完再进行后续操作。
3.注意事项
①.简单短小的函数(5行以内)建议写成内联函数,如递归函数、大函数等不建议使用。频繁调用的小函数也可以写成内联函数,减少函数调用的开销,提高效率。
②.内联函数只是一种建议,代码实际是否会被内联是由编译器决定的,现代编译器通常比程序员更擅长做内联决策。假如你将一个复杂的递归函数写成内联函数,编译器实际上也不会把函数调用替换成函数体。
③.内联函数的声明定义不可以分开(即写在不同文件),最简单的实现方式就是把声明定义一起写在头文件(或只写定义)。
④.内联函数会造成代码膨胀,例如某个函数被调用100次,那么它也将被复制100次。
⑤.如图为宏定义函数和内联函数的对比,除非特定情况,否则总是优先使用内联函数而非宏。
感谢阅读,欢迎一键三连! ^ _ ^








