内联函数最初的目的:
- 代替部分
#define
宏定义 - 替代普通函数:提高程序的运行效率
如果一些函数被频繁调用,不断地有函数进入函数栈,会造成栈空间的大量消耗。因此引入了内联函数。
函数调用是有时间和空间开销的。执行一个函数之前要将实参、局部变量、返回地址等压入栈中,然后执行函数体中,执行完毕后还要让之前压入栈中的数据都出栈。如果函数体代码比较多,需要较长的执行时间,那么函数调用机制占用的时间可以忽略:如果函数只有一两条语句,那么调用机制的时间开销就就不容忽视。
内联函数是在编译阶段将函数展开,而不用将函数地址压入栈,避免调用的开销,但增大了可执行程序的体积。因此内联函数一般比较小,用于大量调用的场合。如果在类体内定义实现,那么就是内联函数;也可以在类内用inline声明,在体外实现。
其实上面这些还没触及到本质,还有以下几条:
inline只是我们对编译器提出的一个申请,是否真按内联函数处理取决于编译器,比如开启优化选项时才考虑内联函数
函数不能有循环和递归,不能太大,否则仍是普通函数
编译器的内联看起来就像是代码的复制与粘贴,这与预处理宏是很不同的:宏是强制的内联展开,可能将会污染所有的命名空间与代码,将为程序的调试带来困难,所以最好用内联函数代替宏
内联函数无法随程序库升级而升级,比如修改了一个内联函数,那么所有用到它的地方都要重新编译,而普通函数做修改后,程序只需要重新链接它,效率比重新编译高
如果一个内联函数会在多个源文件中被用到,那么最好把它定义在头文件中,否则必须在调用该函数的每个文件中定义
构造函数和析构函数不适合做内联函数,编译器在编译期间会给你的构造函数和析构函数额外加入很多的代码,像成员函数的构造和析构等代码,所以通常构造和析构函数比表面上看起来的要多,并不适合作为内联函数
内联函数和宏的区别:
内联函数展开在编译阶段,宏在预处理阶段
内联函数会经过编译器安全检查,宏定义的参数没有类型的概念,只有在宏展开以后,才由编译器检查语法,这就存在很多的安全隐患
详细内容看《Effective C++》条款30