C++函数重载、内联函数和引用

C++函数重载、内联函数和引用

  • 函数重载
    • 函数重载机制
    • extern "C"
    • 重载和作用域
    • 重载解析
    • 确定重载函数的三个步骤
    • 指针类型也会对函数的重载造成影响
  • 默认形参
  • 内联函数
  • 引用
  • C++的内存管理
    • new/delete
    • 数组的分配与释放
    • 内存分配失败

函数重载

在同一作用域下,函数名相同,参数列表不同的函数构成重载关系。

函数重载机制

C++代码在编译时会把函数的参数类型添加到参数名中,借助整个方式来实现函数重载,也就是说C++函数在编译期间经历了换名的过程。
因此,C++代码不能调用C函数(C语言编译器编译出的函数)

extern “C”

告诉C++编译器按照C语言的方式声明函数,这样C++就可以调用C编译器编译出的函数(C++的目标文件可以与C目标文件合并生成可执行程序)。
如果C想调用C++编译出的函数,需要将C++函数的定义用extern "C"包括一下。
注意:如果两个函数名一样,一定会冲突。

重载和作用域

函数的重载关系发生在同一作用域下,不同作用域下同名函数构成隐藏关系。

重载解析

当调用函数时,编译器根据实参的类型和形参的匹配情况,选择一个确定的重载版本,这个过程叫重载解析。
实参的类型和形参的匹配情况有三种:

1、编译器找到与实参最佳的匹配函数,编译器将生成调用代码。
2、如果编译器找不到匹配函数,会给出错误信息
3、编译器找到好几个匹配函数,但是没有一个最佳的,这种错误叫二义性。

在大多数情况下,编译器都能立即找到一个最佳的调用版本,但如果没有,编译器就会进行类型提升,这样备选函数中就可能具有多个可能调用的版本,这样就可能产生二义性错误。

确定重载函数的三个步骤

1、候选函数
函数重载的第一步就是确定所有可调用的函数的集合(函数名、作用域),该集合中的函数就是候选函数。
2、选择可行性函数
从候选函数中选择一个或多个函数,选择的标准时参数个数相同,而且通过类型提升实参可被隐式转换为形参。
3、寻找最佳匹配
优选每个参数都完全匹配的方案,其次时参数完全匹配的个数,再其次是浪费内存的字节数。

指针类型也会对函数的重载造成影响

C++函数的形参如果是指针类型,编译时函数名中会追加Px

默认形参

  • 在C++中函数的形参可以设置默认值,调用函数时,如果没有提供实参,则使用默认形参。
  • 如果形参只有一部分设置了默认形参,则必须靠右排列。
  • 函数的默认形参是在编译阶段确定的,因此只能使用常量、常量表达式、全局变量数据作为默认值。
  • 如果函数的声明和定义需要分开,只需要在函数声明时设置默认形参即可。
  • 默认形参会对函数重载造成影响,设置默认形参时一定要慎重。

内联函数

1、普通函数调用时是生成调用指令(跳转),然后当代码执行到那个位置时,跳转到函数所在的代码段中执行。
2、内联函数就是把函数编译好的二进制指令直接复制到函数的调用位置。
3、内联函数的优点就是能够提高程序的运行速度(因为没有跳转也不需要返回),但这样会导致可执行文件增大(冗余),也就是牺牲空间来换取时间。
4、内联分为显式内联和隐式内联

	显式内联:在函数前加 inline(C语言C99标准也支持)
	隐式内联:结构、类中内部直接定义成员函数,则该类型函数会被自动优化成内联函数。

5、宏函数在调用时会把函数体直接替换到调用位置,与内联函数一样也是使用空间来换取时间,因此内联函数和宏函数的优缺点:

	1、宏函数不是真正的函数,只是代码替换,不会有参数压栈、出栈以及返回值,也不会检查参数类型,因此所有类型都能使用,但这样会有安全隐患
	2、内联函数是真正的函数,函数调用时会进行传参,会进行压栈、出栈可以有返回值,并检查参数类型,但这样就不能通用,如果想被多种类型调用需要重载。

6、内联适用的条件

	1、由于内联会造成可执行文件变大,并且增加内存开销,因此只有频繁调用的简单函数适合作为内联函数。
	2、调用比较少的复杂函数,内联后并不显著提高性能,不足以抵消牺牲空间带来的损失,所以不适合内联。
	3、带有递归特性和动态绑定特性的函数,无法实施内联,因此编译器会忽略声明部分的inline关键字。

引用

引用就是取艺名。
1、引用的基本特性

引用就是取别名,声明一个标识符为引用,就表示该标识符是另一个对象的外号。
1、引用必须初始化,不存在空引用,但有悬空引用(变量死了,名还留着)。
2、可以引用无名对象,临时对象,但必须使用常引用
3、引用不能更换目标
4、引用具有const属性
引用一旦完成了定义和初始化就和普通变量名一样了,它就代表了目标,一经引用终身不能引用其他目标。

2、引用型参数

1、引用当作函数的参数能达到指针同样的效果,但不仅具备指针的危险,而且还比指针方便。
2、引用可以非常简单实现函数间共享变量的目的,而且是否使用引用由被调函数说了算。
3、引用当作函数的参数还能提高传递参数的效率,指针至少需要4字节的内存,而引用只是增加一条标识符与内存之间的映射。

3、引用型返回值

1、不要返回局部变量的引用,会造成悬空引用。
2、如果返回值是一个临时值(右值),如果非要使用引用接收的话,得用常引用(const)。
注意:C++中的引用是一种取别名的机制,而C语言中的指针是一种数据类型(代表内存编号的无符号整数)。

C++的内存管理

new/delete

C++具备申请/释放堆内存功能的运算符new/delete,相当于C语言种的malloc和free。

new 类型;	会自动计算类型所需要字节数,然后从堆中分配对应字节数的内存,并返回内存的首地址(具备类型)。
delete 指针;	会自动释放堆内存。
注意:new/delete 与 malloc/free不能混用,因为new和delete会自动调用类、结构的构造函数、析构函数。

数组的分配与释放

1、new 类型[n];	n表示数组长度,如果类、结构会自动调用n次构造函数
2、delete[] 指针;	通过new[]分配的内存,逆序通过delete[]释放
3、new[] 返回值前4个字节种存放着数组长度

内存分配失败

当分配的内存过大,没有能满足需求的整块内存就会抛出异常,std::bad/~alloc。

你可能感兴趣的:(C++,C++函数重载,C++引用)