inline函数解析

inline函数的优势:

比宏优秀,像函数一样使用但是没有函数调用那么大的开销

编译器的最优化机制有能力对不含函数调用的代码进行语境最优化

inline的缺点:

目标码膨胀,内存空间消耗增加,还容易造成虚内存机制的额外换页行为,增加开销,降低缓冲命中率,造成效率损失,但是反之而言,如果inline函数很小,产生的目标码比函数调用产生的目标码还小,那么无疑会增加效率

注意:inline是申请,不是强制命令。

隐式申请:

class person

{

public:

int age() const {return 43;} //隐式inline申请

}

显示申请:

template<tempname T>

inline const T& std::max(const T& a,  const T&b)

{return a<b?b:a;}

inline函数通常一定要放置于头文件(template也要放在头文件,因为模板具现也是编译期行为),因为inline通常是编译期动作,虽然有些编译器是连接期和运行期(.net cli)处理inline,但是很少。同样的virtual也不会被inline因为虚函数意味着运行期确定函数,同样的涉及递归,循环等复杂函数也不会inline,同样的,以函数指针形式调用的函数也不会被inline,因为函数指针必须指向存在的函数实体,而不是inline。

综上:inline的实现和编码与编译器都有关系。

注意:不要将构造函数和析构函数inline

构造函数如果:

class a

{

public:

a(){};//隐式inline申请

}

通常构造函数由编译器自动添加一些目标码,构造所有成员,即使你什么都没写,所以真实的构造和析构函数是很复杂的,inline不是很恰当。


如果inline函数改变,那么必须重新编译,如果是函数调用的话,客户只需要重新连接就好了,如果程序库采用动态链接,那么甚至不用额外处理


inline会造成调试困难,因为不能对inline函数设置断点,大多数编译器支持在调试版中禁止inline


对inline的态度:一开始不要将任何函数声明为inline,或者只将一定成为inline的函数设置为inline。对日后调试有好处,之后再用inline或其它方法将代码瘦身。


总结:大多数inline被限制在小型的频繁使用的函数身上,可以使代码膨胀最小,程序提升效果最好。


备注:inline成功意味着目标码中可能看不到call指令,但是现在编译器已经聪明到可以自动判断一个函数是否适合inline,因此源文件中的inline往往不是必须的,头文件因为vague linkage的原因还是要 inline的(每个编译单元生成弱定义,由连接器选择一个)。

通过观察class template 中的短成员函数有没有被inline可以判断当前是调试版本还是发布版本

g++ -wall fun.cc

nm ./ a.out |grep size|c++filt

会出现短函数,因为是-o0编译,调试版本

g++ -wall -O2  fun.cc

nm ./ a.out |grep size|c++filt

不会出现短函数,因为是O2编译,发布版本,被优化了

class中的析构函数一般都是inline的,为了防止代码碰撞,编译错误,要有意显示noinline声明

现代编译器编译和连接更模糊了,现在g++的 -flto选项可以使inline在连接期做

而且现在g++中有大量内置函数,在应用一些常用函数的时候不一定会真正调用库函数,优化更方便

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值