C++——内联函数

内联函数是C++中为提升程序运行效率的一种方法,它避免了函数调用的栈帧建立等开销。与宏相比,内联函数更安全,支持调试且编写更直观。然而,内联函数并不适用于大型或包含循环的代码,且不应声明与定义分离,否则可能导致链接错误。编译器会根据情况决定是否进行内联优化。宏虽然能提高性能,但存在调试困难和类型安全问题,C++提供了内联函数和const等技术作为替代。
摘要由CSDN通过智能技术生成

目录

1. 概念

2.特性

3. 经典面试题 

1. 概念

inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数压栈的开销,内联函数提升程序运行的效率。

以Add函数为例:

int Add(int x, int y)
{
	int z = x + y;
	return z;
}

上述Add函数如若频繁调用,则效率上会存在一定的损失。假设我调用10次,那么就要建立十次栈帧,建立栈帧又要保存寄存器,压参数等等一系列操作都会造成效率损失。

  • 在先前学习的C语言中,就给出了解决方案:
#define ADD(x, y) ((x) + (y))
  • 既然用宏就可以解决,C++为何引出inline?

使用宏确实可以帮助我们避免调用栈帧继而不会造成效率损失,但是宏的写法上欠妥,我们需要注意结尾不能加分号,要注意优先级带来的问题而频繁加括号……C++为了填补宏书写规则麻烦的坑,专门出了一个更为方便书写的,也就是今个要谈论的内联函数(inline)。综上,结论如下:

  1. 解决宏函数晦涩难懂,容易写错的问题;
  2. 解决宏不支持调试,不支持类型安全的检查等问题。
  • 内联函数(inline)如何使用?

只需要在函数前面加上inline即可

inline int Add(int x, int y)
{
	int z = x + y;
	return z;
}

此时我们再调用函数就不会再建立栈帧了,函数直接会在调用的地方展开。

  • 内联函数(inline)如何支持调试的呢?

需要查看其反汇编,查看方式:

  1. 在release模式下,查看编译器生成的汇编代码中是否存在call Add;
  2. 在debug模式下,需要对编译器进行设置,否则不会展开(因为debug模式下,编译器默认不会对代码进行优化,以下给出vs2013的设置方式);

 

 

仔细看,此时每调用一次Add函数,均不会有call指令了, 此时再和我们没有加inline调用栈帧的版本对比下:

  •  综上:inline的好处如下:
  1. debug支持调试;
  2. 不易写错,就是普通函数的写法。

2.特性

  1. inline是一种以空间换时间的做法,省去调用函数额开销。所以代码很长或者有循环/递归的函数不适宜使用作为内联函数。
  2. inline对于编译器而言只是一个建议,编译器会自动优化,如果定义为inline的函数体内有循环/递归等等,编译器优化时会忽略掉内联。
  3. inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到。
  • 1、解释特性1和2:

假设我们现在有一个10行的函数,如若该函数有1000个调用的地方,如果inline替换,则是1000*10条指令,如果不替换,则是1000+10条指令,二者相差10倍之大,由此可见,代码很长或调用次数过多或存在循环/递归不适宜用内联函数

代码演示:

  • 代码演示:

 此段代码还能够证明inline对于编译器只是一个建议 。

  • 解释特性3:inline不建议声明和定义分离
// F.h文件
#include <iostream>
using namespace std;
inline void f(int i);
// F.cpp文件
#include "F.h"
void f(int i)
{
	cout << i << endl;
}
// test.cpp文件
#include "F.h"
int main()
{
	f(10);
	return 0;
}

此段代码中,inline函数的声明和定义分离,此时我们编译没有错误,可是在链接时发生错误:

原因如下:

F.h声明了我是一个内联函数,F.h文件会在F.cpp文件展开,要注意,inline函数在编译过程中不会生成地址,其符号表里没有地址,F.cpp文件中调用时找不到该函数地址。所以inline不建议声明和定义分离。

解决方法如下:

将声明和定义都放到F.h文件,就没有问题了,总之就是声明定义不能分离。

3. 经典面试题 

  • 问题1:宏的优缺点?

优点:

  1. 增强代码的复用性;
  2. 提高性能。

缺点:

  1. 不方便调试宏(因为预编译阶段进行了替换);
  2. 导致代码可读性差,可维护性差,容易误用;
  3. 没有类型安全的检查。
  • 问题2:C++有哪些技术代替宏?
  1. 常量定义,换用const;
  2. 函数定义,换用内联函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值