C++中的内联函数
1. 定义
内联函数是C++的增强特性之一,用来降低程序的运行时间。当内联函数收到编译器的指示时,即可发生内联:编译器将使用函数的定义体来替代函数调用语句,这种替代行为发生在编译阶段而非程序运行阶段
它们看起来像函数,运作起来像函数,比宏要好得多,使用时还不需要承担函数调用的开销。当内联一个函数时,编译器可以对函数体执行特定环境下的优化工作,这样的优化对”正常“的函数调用是不可能的
下面是一个实例,使用内联函数来返回两个数中的最大值:
#include <iostream>
using namespace std;
inline int Max(int x, int y)
{
return (x > y)? x : y;
}
// 程序的主函数
int main( )
{
cout << "Max (20,10): " << Max(20,10) << endl;
cout << "Max (0,200): " << Max(0,200) << endl;
cout << "Max (100,1010): " << Max(100,1010) << endl;
return 0;
}
上面的代码运行后结果为:
Max (20,10): 20
Max (0,200): 200
Max (100,1010): 1010
2. 细节
- 内联函数的关键字为inline
- 内联函数是一个对编译器的建议,如果函数过于复杂,编译器会不接受你的建议而将函数处理成普通的函数
- 对内联函数进行任何修改,都需要重新编译函数的所有客户端,因为编译器需要重新更换一次所有的代码,否则将会继续使用旧的函数
-
inline关键字必须和函数体定义放在一起才可以实现内联,仅仅将inline放在函数声明之前不起任何作用。inline是一个用于实现的关键字而不是一个用于声明的关键字
注意:这个说法是《高质量程序设计指南C++/C语言》中的说法,在《C++Primer》中提到应在函数的声明与定义中都加inline
《高质量程序设计指南C++/C语言》:
关键字inline 必须与函数定义体放在一起才能使函数成为内联,仅将inline 放在函数声明前面不起任何作用
如下风格的函数Foo 不能成为内联函数:
inline void Foo(int x, int y); // inline 仅与函数声明放在一起
void Foo(int x, int y){}
而如下风格的函数Foo 则成为内联函数:
void Foo(int x, int y);
inline void Foo(int x, int y) // inline 与函数定义体放在一起{}
所以说,inline 是一种“用于实现的关键字”,而不是一种“用于声明的关键字”。一般地,用户可以阅读函数的声明,但是看不到函数的定义。尽管在大多数教科书中内联函数的声明、定义体前面都加了inline 关键字,但我认为inline 不应该出现在函数的声明中。这个细节虽然不会影响函数的功能,但是体现了高质量C++/C 程序设计风格的一个基本原则:声明与定义不可混为一谈,用户没有必要、也不应该知道函数是否需要内联。
-
在类中定义的成员函数将自动转化为内联函数
注意:必须要在类内完成函数定义才会转化成内联函数,在类内声明而在类外定义则不会转化,当然只有函数非常简单时编译器才会处理成内联函数
- 虚函数不允许内联
- 在调试时查看汇编会发现内联函数还是使用了call指令进行了函数调用而没有用在调用处展开的方式处理,这是因为debug版本上inline是不起作用的;inline只有在release版本下才能出现
3. 内联函数的优缺点分析
优点:
- 它通过避免函数调用所带来的开销来提高你程序的运行速度
- 当函数调用发生时,它节省了变量压栈、出栈的开销
- 它避免了一个函数执行完返回原现场的开销
- 通过将函数声明为内联,可以把函数定义放在头文件内
缺点:
- 因为代码的扩展,内联函数增大了可执行程序的体积
- C++内联函数的展开是编译阶段,这就意味着如果内联函数发生了改动,那么就需要重新编译代码
- 当把内联函数放在头文件中时,它将会使头文件的信息变多
- 有时候内联函数并不受到青睐,比如在嵌入式系统中,嵌入式系统的存储约束可能不允许体积很大的可执行程序
4.内联函数和宏的区别
- 内联函数在运行时可调试,而宏不可以
- 编译器会对内联函数的参数类型做安全检查或自动类型转换(同普通函数),而宏则不会
- 内联函数可以访问类的成员变量,宏则不能
- 在类中定义的成员函数,自动转化为内联函数
- inline在和宏相比没有付出任何额外代价的的情况下更安全,《Effective C++》中”Prefer consts,enums,and inlines to #defines“以及《高质量程序设计指南C++/C语言》中”用函数内联取代宏“都建议用inline函数代替带参宏