您现在的位置是:首页 >技术杂谈 >C++ 学习 ::【基础篇:06】:C++ (inline)内联函数的介绍及其出现的意义【对比于 C语言宏函数】网站首页技术杂谈
C++ 学习 ::【基础篇:06】:C++ (inline)内联函数的介绍及其出现的意义【对比于 C语言宏函数】
简介C++ 学习 ::【基础篇:06】:C++ (inline)内联函数的介绍及其出现的意义【对比于 C语言宏函数】
本系列 C++ 相关文章 仅为笔者学习笔记记录,用自己的理解记录学习!C++ 学习系列将分为三个阶段:基础篇、STL 篇、高阶数据结构与算法篇,相关重点内容如下:
- 基础篇:类与对象(涉及C++的三大特性等);
- STL 篇:学习使用 C++ 提供的 STL 相关库;
- 高阶数据结构与算法篇: 手动实现自己的 STL 库 及 设计实现高阶数据结构,如 B树、B+树、红黑树等。
学习集:
本期内容:C++ (inline)内联函数的介绍及其出现的意义【对比于 C语言宏函数】
目录:
1. inline 内联函数的概念及使用方式
2. 关于函数栈帧的简单说明
3. 内联函数出现的意义:减少栈帧的开销提升程序运行效率
- - 3.1 高耗栈帧情形(内联函数适用情形)
- - 3.2 C 语言的解决方案:宏函数
- - 3.3 C++ 的解决方案:内联函数
4. 内联函数的注意点
【 C++学习合集链接 】
1. inline 内联函数的概念及使用方式
- 以 inline 修饰的函数叫做内联函数;
- 编译时 C++ 编译器会在调用内联函数的地方展开,没有函数调用建立栈帧的开销,内联函数提升程序运行的效率!!!
内联函数的使用方式:inline 类型 函数名(){}
/* C++ 方式定义一个内联函数:实现 add 加和。 */
inline int Add(int a, int b){
return a+b;
}
2. 关于函数栈帧的简单说明
简而言之,函数在被调用时,编译器是会给被调用函数在栈区分配一个空间的!即:该过程使用空间申请的!
3. 内联函数出现的意义:减少栈帧的开销提升程序运行效率
3.1 高耗栈帧情形(内联函数适用情形)
若程序中出现较为电销的函数(1-10行),同时又频繁调用(如:10万次)。
如:在排序算法中使用的 swap 函数,对大量数据进行排序时,交换次数水涨船高!
- C语言的解决方式:使用宏函数!
- C++ 的解决方式:内联函数!
3.2 C 语言的解决方案:宏函数
宏的优缺点:
- 缺点:
- 可读性差;
- 没有类型安全检查、不方便调试(直接替换如代码中)
- 优点:代码可维护性高(一改全改)、宏函数提高效率(减少栈帧建立)
/* C 语言方式定义一个宏函数:实现 add 加和。 */
#define ADD(a+b) {(a)+(b)} /* 写法错误 */
#define ADD(a,b) {(a)+(b)} /* 写法错误 */
#define ADD(a,b) a+b /* 写法错误 */
#define ADD(a,b) {return a + b;} /* 写法错误 */
#define ADD(int a, int b) {return a + b;} /* 写法错误 */
#define ADD(a,b) ((a)+(b))
int main(){
// 一般而言,写出的宏函数能解决以下形式的适配问题基本就对
ADD(1, 2);
if(ADD(1, 2)){}
ADD(1, 2)*3;
int x = 1, y = 2;
ADD(x | y, x & y);
return 0;
}
3.3 C++ 的解决方案:内联函数
- 内联函数会在被调用处直接展开,好比在被调用处直接写了对应的函数功能(实现内联函数相当于就是提供代码复用性)
- 内联函数几乎解决了宏(函数)的缺点!
- C++ 中基本不再建议使用宏!
#include<iostream>
using namespace std;
int sum(int a, int b) {
return a + b;
}
inline double sum(double a, double b) {
return a + b;
}
int main() {
sum(1, 1);
sum(1.2, 2.2); /* 调用内联函数相当于在此处直接实现两个 double 值的运算 */
return 0;
}
4. 内联函数的注意点
- inline 是一种 以空间换时间 的做法,如果编译器将函数当成内联函数处理,在编译阶段,会用函数体替换函数调用,缺陷:可能会使目标文件变大,优势:少了调用开销,提高程序运行效率。
- inline 对于编译器而言只是一个建议,不同编译器关于 inline 实现机制可能不同,一般建议:将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)、不是递归、且频繁调用的函数采用 inline 修饰,否则编译器会忽略inline特性。
- inline不建议声明和定义分离,分离会导致链接错误。因为 inline 被展开,就没有函数地址了,链接就会找不到。
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。