内联的总结:
使用条件:短小,调用频繁的函数
内联的缺点:增加了编译的时间,不便于调试
内联的优点:避免了函数调用带来的开销,同时为编译器进一步优化提供可能(调用间的优化编译器一般无能为力,但是内联后编译器可以进一步优化)。对于一些微小的方法内联(一般就是几条指令),可以减少最终的可执行文件(因为调用开销也需要一些指令的)
内联不当的后果:造成代码膨胀,导致与性能相关的方负面影响:缓存失败和页面错误。(缓存与页面大小固定,代码膨胀以及内联的方法可能存在多个地址,这些都导致缓存或页面不足,频繁的切换的可能性大大提高。)
内联技巧:
1、条件内联
内联增加编译时间,并且不便于调试,而产品发布时,希望内联以增加性能,此时可以采用条件内联。使用方式如下:
C++ Code
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
x.h
#ifndef _X_H #define _X_H class A { void y(); }; #if defined(INLINE) #include "x.inl" #endif #endif x.inl #if !defined(INLINE) #define inline #endif inline void A::y() {} x.cpp #if !defined(INLINE) #include "x.inl" #endif |
2、选择内联
由于对非短小但频繁的代码内联可能造成代码膨胀,此时我们希望只对在核心路径上的调用内联,而其他不内联,此时我们可以采用如下方式:
对该方法创建两个不同的接口名,其中一个接口调用内联的接口名,核心路径上的调用,则使用内联的接口名,非核心路径上使用非内联接口名。如:
C++ Code
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
#ifndef _X_H
#define _X_H class A { void y(); void inline_y(); }; #if defined(INLINE) #include "x.inl" #endif #endif x.inl #if !defined(INLINE) #define inline #endif inline void A::inline_y() { ... } x.cpp #include "x.h" void A::y() { inline_y(); } |
3、递归内联
一般情况下,内联不能使用在递归上。这里的递归不是传统意义上的递归,这里是手动展开几层,然后再递归调用
如在二叉树查找中中序遍历的递归操作如下:(有些内容省了)
C++ Code
1
2 3 4 5 6 |
void binary_tree::key_out()
{ if(left) left->key_out(); cout << id << endl; if(right) right->key_out(); } |
使用内联递归的方法:
C++ Code
1
2 3 4 5 6 7 8 9 10 11 12 13 |
inline
void binary_tree:
INLINE_key_out() { if(left) left->key_out(); cout << id << endl; if(right) right->key_out(); } void binary_tree::key_out() { if(left) left->INLINE_key_out(); cout << id << endl; if(right) right->INLINE_key_out(); } |