1. 内联函数
- 🍎 概念
以inline
修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调用建立栈帧的开销,内联函数提升程序运行的效率。
(假如我们要调用一个函数100w
次,如果建立100w
个栈帧的话,效率极低,所以引入内联函数。C语言
是没有内联函数的,那它怎么解决这个问题呢? -----C语言
则用 宏函数解决)
- 🍎 如何查看呢?
-
- 在
release
模式下,查看编译器生成的汇编代码中是否存在call Add
- 在
-
- 在
debug
模式下,需要对编译器进行设置,否则不会展开(因为debug模式下,编译器默认不
会对代码进行优化,以下给出设置方式)
- 在
- 🍎 内联函数的特性
// F.h 文件
#include <iostream>
using namespace std;
inline void f(int i);
// F.cpp 文件
#include "F.h"
void f(int i)
{
cout << i << endl;
}
// main.cpp 文件
#include "F.h"
int main()
{
f(10);
return 0;
}
// 链接错误:main.obj : error LNK2019:
无法解析的外部符号 "void __cdecl
f(int)" (?f@@YAXH@Z),该符号在函数 _main 中被引用
2. 内联函数和宏定义的区别
3. 宏函数
- 下面定义了一个
a + b
的宏函数,从中可以看出宏函数有很多缺点:
🐧① 语法复杂,坑很多,不容易控制。
🐧② 不能调试;
🐧③ 没有类型安全检查;
#define ADD(a, b) ((a) + (b))
为什么要在对 `a` 和 `b`加上括号呢?
因为运算符优先级的原因:
例如: ADD(x & y , m | n) 因为 + 的运算符优先级更高,所以该式子变成了: x & (y + m) | n 错误的
4. 宏的优缺点
- 🍎
C++
中类型安全检查的概念
5. 小扩展
static
改变函数的属性,只在当前文件可见,底层函数不会进符号表。
把地址加到符号表是为了方便别人调用,但是内联函数不会,因为内联函数在调用的地方已经展开了,别人不用调用。
static
和 内联函数一样,也不会进符号表。
- 要想做到多个文件包含同一个函数的实现有以下方法:
🍎 " 定义" 的意思实际上就是开空间 — 对象实例化,如果函数没有采取声明和定义分离的编码方式,我们在多个文件下包含了该函数的话,就表示我们重复 “定义”了该函数了!
🍎 如果我们不适用声明和定义分离的形式,那么函数必须是内联函数或者是 static
修饰的函数,否则会重复定义报错。