[C++] C++基础之inline的使用

总的使用原则: 慎重使用inline,一般可以考虑不用inline,只在能有效减少调用耗时的情况下使用inline;实际编程时最初的原则是不要内联任何函数,除非函数确实很小很简单。

1. 为什么要使用inline

当一个小的函数被非常频繁的调用时,我们为了减少不必要的计算开销,会将其声明为inline,这样就在没有调用开销的情况下使用这个函数。

知识点1: 使用inline的目的是减少函数调用开销,所以只有调用开销相对于函数执行很大时inline的意义才更大。

2. inline如何减少调用开销的,与宏有什么区别

2.1 inline如何工作的?

  • inline基本思想在于将每个函数调用以它的代码体来替换

2.2 与宏的区别?

既然都是平替代码,那么inline和宏又有什么区别(感觉都是一种替换策略),这就需要说到宏存在的两个问题

  • 宏定义在形式上类似于一个函数,但在使用它时,仅仅只是做预处理器符号表中的简单替换,因此它不能进行参数有效性的检测,也就不能享受C++编译器严格类型检查的好处;另外它的返回值也不能被强制转换为可转换的合适的类型
  • 在C++中引入了类及类的访问控制,这样,如果一个操作或者说一个表达式涉及到类的保护成员或私有成员,你就不可能使用这种宏定义来实现

知识点2: inline 推出的目的,也正是为了取代这种表达式形式的宏定义,它消除了宏定义的缺点,同时又很好地继承了宏定义的优点。

3. 那么inline会强制有效吗?

不会, inline 就像register一样,只是对编译器提示作用,编译器会根据实际代码情况决定是否对函数进行inline操作。比如,你将一个递归函数指定为inline,编译器就会忽略这个inline,将这个函数还原成普通函数。

知识点3: inline只是提示作用而不是强制的

4. 在函数声明前使用inline有效吗?

inline只在函数定义时使用是有效的,在函数的声明时使用没有意义。

知识点4: inline只有在函数定义时使用才有效。

5. 绝对不会inline的函数有哪些?

  • 包含循环和递归函数,某些虚函数

知识点5: inline的死对头。

6. 有哪些函数会自动隐式内联

  • 对于类方法,定义在类体内部的一些方法自动成为内联方法。 比如getter 和setter函数; 但是注意不要在构造和析构函数中使用,虽然这两类函数显式的代码体小,但是隐式的代码体会很大(因为存在大量对成员变量的初始化和销毁操作在),所以实际上inline可能是作用在大函数体上的,从而带来inline的副作用(代码膨胀和失效。)

知识点6: 类中一些方法会自动成为内联方法。内联函数最重要的使用地方是用于类的存取函数。

7. 为什么要求我们只对小的函数进行inline?

因为长而复杂的函数使用inline存在两个问题:

  • 复杂的函数用inline没有优势:inline函数通过省去函数调用的开销,从而提高函数的执行效率,但是如果函数体内代码的执行时间相比于函数调用时间长的多的话,inline函数也就没有什么优势了。
  • 长且复杂的函数inline会让代码膨胀(因为平替),增加整个目标代码的体积,而过分地使用内联所产生的程序会因为有太大的体积而导致可用空间不够。即使可以使用虚拟内存,内联造成的代码膨胀也可能会导致不合理的页面调度行为(系统颠簸),这将使你的程序运行变慢;此外过多的内联还会降低指令高速缓存的命中率,从而使取指令的速度降低。

如果函数小,会缩减目标代码的大小(少了调用代码)

知识点7: inline只在小函数上使用会有好处。

8. 为什么inline函数多定义在header文件中

  • 在调用内联函数时,要保证内联函数的定义让编译器"看"到,也就是说内联函数的定义要在头文件中,这与通常的函数定义不一样。

特殊情况,inline函数在header中会有问题,比如inline函数因为一些原因,不能被编译器内联,那么?

  • 旧的编译器规则:对于未被内联的内联函数,编译器把它当成被声明为static 那样处理,即,使它局限于当前被编译的文件。 但是如果这个内联函数中有static局部变量,那么就会存在静态局部变量会存在两份拷贝的情况。
  • 新的编译器规则:为f生成代码时就象它是一个普通的"外联"函数一样, 可以理解为extern 指示的函数一样。

知识点8: inline函数一般建议在header中定义,但是需要考虑inline失效的情况下导致的问题。 比如:如果函数中包含静态对象,通常要避免将它声明为内联函数。

9. 内联函数可以用函数指针方式使用吗?

  • 如果程序中要取一个内联函数的地址,编译器就必须为此生成一个函数体。 也就是没有了函数体平替的机制。

知识点9: inline函数使用函数指针传递,则不会执行inline的平替机制。

10. 虚函数不可inline?

  • 一般来说虚函数不要inline
  • The main reason for making a virtual function inline is to place its definition in the class, either for convenience or to document its behavior, e.g., for virtual accessors and mutators.

11. inline函数在程序设计方面有什么影响吗?

  • 如果过多的使用inline函数,那么想对程序库中的内联函数进行二进制代码升级是不可能的。换句话说,如果Func是库中的一个内联函数,使用方会将Func的函数体编译到自己的程序中。如果程序库的设计者后来要修改Func,所有使用Func的用户程序必须重新编译。相反,如果Func是非内联函数,对f的修改仅需要用户重新链接,这就比需要重新编译大大减轻了负担;如果包含这个函数的程序库是被动态链接的,程序库的修改对用户来说完全是透明的。

12. 一个函数可以强制不内联或者强制内联

目的是什么?

__noinline__ void function();
__forceinline__ void function();

13. Google Code Guide经验法则

  • 最好inline不超过10行的函数:A decent rule of thumb is to not inline a function if it is more than 10 lines long. Beware of destructors, which are often longer than they appear because of implicit member- and base-destructor calls!
  • inline函数中最好不要有循环或switch: Another useful rule of thumb: it’s typically not cost effective to inline functions with loops or switch statements (unless, in the common case, the loop or switch statement is never executed).

Reference

  • https://google.github.io/styleguide/cppguide.html#Inline_Functions
  • https://www.cnblogs.com/yaowen/p/4777810.html
  • Effective C++: 条款30 彻底了解inlining的里里外外
  • https://upimg.baike.so.com/doc/6842554-7059853.html
  • https://www.cnblogs.com/alex-tech/archive/2011/03/24/1994273.html
  • 21
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值