Item 30 内联函数

内联函数像函数,但是却省下了调用函数的时空开销。但实际上,编译器做的不止于此。因为编译器的优化一般是针对一整块没有函数调用的代码,所以,如果你使用了内联函数,编译器也许会根据上下文再优化一下内联函数的函数体。

使用内联函数的代价:会使目标文件变大;由此也更耗内存;太多的内联函数导致内存分页过多;最后因频繁的页面交换降低CPU的缓存利用。但是,当内联函数非常短的时候,目标文件反而变小;最后反而提高了CPU的缓存利用率。

关键字inline只是对编译器的一个请求,而非命令。编译器有可能不理会这个请求。

隐式的内联函数请求,就是把函数体放到类的定义里:

 

 

显式的内联函数请求,就是使用了inline关键字:

 

 

上面这个max既是内联函数,又是模板函数,而且都定义在头文件里。由此许多程序员认为,模板函数必须是内联的。
这个结论错误,而且有害。

内联函数要放在头文件里。因为大多数编译环境在编译时处理内联。它们要搜索头文件,找到内联函数的定义,然后在调用的地方用函数体去做替换工作。
(少数编译器在链接时做内联工作,基于.Net CLI的托管环境甚至在运行时做内联的工作。这是C++世界的例外,不予考虑。)

模板要放在头文件里。因为编译器也要知道定义才能在编译时做模板实例化。(也有例外。)

但是,模板和内联完全不相关。写模板的时候,需要内联的时候才内联(无论隐式还是显式)。

编译器看到复杂的函数时不会内联它:有循环的、有递归的、有虚函数调用的。用-Winline可以让编译器在忽略一个内联请求时发出一个警告。
编译器对使用函数指针做的函数调用不做内联处理。

 

 

有时,即使你不用函数指针,有的内联函数也不做内联处理。因为有的函数指针是隐形的。

 

 

看那个Derived::ctor,空的,但不能内联。因为一个类的new和delete会发生很多事。C++规定了必须做这些事,然后编译器的实现者们就会让编译器自动在你的程
序中插入各种各样的代码。由此导致ctor不是看上去那么空。
基类的ctor也不能内联,否则会大大影响程序。

库函数内联的话会影响它以后的升级。去掉内联,升级的时候只是重新链接的问题,不会影响编译,不会影响客户的代码。

很多debugger对内联支持不好。

 

和inline有关的GCC开关

 

>>> -fno-inline
忽略所有inline关键字。

>>> -finline-functions
内联所有简单函数。如果该简单函数是static的,那么就不生成汇编码。该选项在-O3时自动启用。

>>> -finline-functions-called-once
所有只调用一次的static函数都做内联处理,即使没有inline关键字。不生成汇编码。该选项在启用-funit-at-a-time时自动启用。

>>> -fearly-inlining
有always_inline标志的函数、非常小的函数都在-fprofile-generate之前做内联处理。该选项默认是开启的。

>>> -finline-limit=n
GCC说内联函数的限制是n=600。

>>> -fkeep-inline-functions
在C程序里,如果内联函数是static的,则编译该函数到目标文件中;在C++程序里,所有内联函数都编译到目标文件里。

>>> -fno-default-inline
在函数体内定义的函数不做内联处理。

>>> -fno-implement-inlines

>>> -fno-implicit-inline-templates

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值