第6课-内联函数分析

1. 常量与宏回顾

  • C++中的const常量可以替代宏常数定义,如:
const int A = 3    <==>    #define A 3

C++中是否有解决方案可以替代宏代码片段呢?

 

2. 内联函数

  • C++中推荐使用内联函数替代宏代码片段

  • C++中使用inline关键字声明内联函数

inline int func(int a, int b)
{
  return a < b ? a : b;
}

  PS:

    (1)内联函数声明时,inline关键字必须和函数定义结合在一起,否则有的编译器会直接忽略内联请求!!!

    (2)在VS2015中,inline关键只要结合了函数声明和函数定义中的一个,就可以内联

  • C++编译器可以将一个函数进行内联编译

  • 被C++编译器内联编译的函数叫做内联函数

  • C++编译器直接将函数体插入函数调用的地方

  • 内联函数没有普通函数调用时的额外开销(压栈、跳转、返回)

  PS:C++编译器不一定满足函数的内联请求!

 

编程实验:内联函数初探

#include <stdio.h>

#define FUNC(a, b) ((a) < (b) ? (a) : (b))

inline int func(int a, int b)
{
    return a < b ? a : b;
}

int main(int argc, char *argv[])
{
    int a = 1;
    int b = 3;
    int c = FUNC(++a, b);
    //int c = func(++a, b);

    printf("a = %d\n", a);  // 宏:3  内联:2
    printf("b = %d\n", b);  // 宏:3  内联:3
    printf("c = %d\n", c);  // 宏:3  内联:2

    return 0;
}

 

  • 内联函数具有普通函数的特征(参数检查返回类型等)

  • 函数的内联请求可能被编译器拒绝

  • 函数被内联编译后,函数体直接扩展到调用的地方

  PS:宏代码片段由预处理器处理,进行简单的文本替换,没有任何编译过程,因此可能出现副作用

  • 现代C++编译器能够进行编译优化,一些函数即使没有inline声明,也可能被内联编译

  • 一些现代C++编译器提供了扩展语法,能够对函数进行强制内联,如:

    - g++:__attribute__((always_inline))属性

    - MSVC:__forceinline

  PS:在VS2015上测试__forceinline也不一定将函数内联,需要将项目->属性->配置属性->C/C++->优化->内联函数扩展设置为:只适用于 __inline (/Ob1)

 

编程实验:内联函数深度示例

#include <stdio.h>

//__forceinline__    // MSVC
__attribute__((always_inline))    // g++
//inline 
int add_inline(int n);

int main()
{
    int r = add_inline(10);
    
    printf("r = %d\n", r);
    
    return 0;
}

inline int add_inline(int n)
{
    int ret = 0;
    
    for(int i = 0; i < n; i++)
    {
        ret += i;
    }
    
    return ret;
}

 

3. 注意事项

  • C++中inline内联编译的限制

    - 不能存在任何形式的循环语句

    - 不能存在过多的条件判断语句

    - 函数体不能过于庞大

    - 不能对函数进行取址操作

    - 函数内联声明必须在调用语句之前

 

6. 小结

  • C++中可以通过inline声明内联函数

  • 编译器直接将内联函数体扩展到函数调用的地方

  • inline只是一种请求,编译器不一定允许这种请求

  • 内联函数省去了函数调用时的压栈跳转返回的开销

 

本文出处:狄泰软件学院

posted @ 2020-03-14 17:22  WisdomMan  阅读(10)  评论(0)    收藏  举报