C++中的内联函数分析

论坛 期权论坛 期权     
C语言与C++编程   2019-7-8 05:46   4699   0
作者:子宇24
链接:https://www.cnblogs.com/dishengAndziyu/p/10902908.html
1、本节课学习 C++ 中才引入的新的概念,内联函数;

2、常量与宏回顾:

  • C++ 中的 const 常量可以替代宏常数定义,如:
    const int A = 3;  #define A 3
    C++ 中如果要使用宏常数,则可以用 const 常数代替;
  • C++ 中是否有解决方案替代宏代码片段呢?
    为了替换宏代码块,内联函数的概念被提出;

3、内联函数用法:

  • C++ 中推荐使用内联函数替代宏代码片段;
    宏代码块看上去像函数但实际不是函数,因此其使用常带有副作用;
    消除这样的副作用需要函数,但是函数的调用有入栈返回等开销,这一点宏代码块没有;
    综合两者有点,避免两者缺点,内联函数被提出来;
  • C++ 中使用 inline 关键字声明内联函数;
  1. 1 inline int func(int a, int b)
  2. 2 {
  3. 3      return a < b ? a : b;
  4. 4 }
复制代码
内联函数在表现形式上和普通函数一样,但是它会被编译器进行优化,编译器直接将内联函数的函数体进行扩展,这个扩展由编译器直接将生成的代码进行扩展,扩展到调用这个内联函数的地方,由编译器进行,所以会进行编译器检查等一些列工作;

inline 可以将一个函数声明为内联函数,但是这种声明是对编译器的一种请求,请求编译器将这个函数进行内联编译,所以编译器可以拒绝内联请求;

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


4、内联函数特点:

  • C++ 编译器可以将一个函数进行内联编译;
  • 被 C++ 编译器内联编译的函数叫做内联函数;
    内联函数在 C++ 中的地位是用来替换 C 中的宏代码块;
  • C++ 编译器直接将函数体插入函数调用的地方;
  • 内联函数没有普通函数调用时的额外开销(压栈,跳转,返回);
    C++ 编译器不一定满足函数的内敛请求;  
    此时内联函数变为普通函数,行为同普通函数;

5、内联函数初探编程实验:

  • main.cpp 文件:
  1. #include
  2. /* 宏代码块 */
  3. #define FUNC(a, b) ((a) < (b) ? (a) : (b))  
  4. /* 声明一个内联函数 */
  5. inline int func(int a, int b)
  6. {
  7.     return a < b ? a : b;
  8. }
  9. int main(int argc, char *argv[])
  10. {
  11.     int a = 1;
  12.     int b = 3;
  13.     int c = FUNC(++a, b); // ==> int c = ((++a) < (b) ? (++a) : (b)); 这里 a 加了两次;
  14.     // int c = func(++a, b);
  15.     printf("a = %d\n", a);
  16.     printf("b = %d\n", b);
  17.     printf("c = %d\n", c);
  18.     return 0;
  19. }
复制代码
宏调用结果:
  1. a = 3  b = 3  c = c
复制代码
函数调用结果:
  1. a = 2  b = 3  c = 2
复制代码
VC 工程属性优化 inline 默认:



VC 工程属性优化 inline 内联:



Eclipse 工程 g++ 编译 inline 内联:



  • 结论:
    内联函数函数请求有可能被拒绝;
    内联函数是存在的,可以替换宏代码块;

6、内联函数特征:

  • 内联函数具有普通函数的特征(参数检查,返回类型等);
    类型更加安全;
    C++ 提供各种方式让大家摒弃 C 中不好的一些特性,内联函数就是其中之一;
  • 函数的内联请求可能被编译器拒绝;
    可以通过配置的方式让编译器支持内联函数的请求;
  • 函数被内联编译后,函数体直接扩展到调用的地方;
    如果内联成功,其效率上可以和宏代码块媲美,且其在类型上比宏代码块安全很多,因此在 C++ 编程中,首选内联函数;
    宏代码片段由预处理器处理,进行简单的文本替换,没有任何编译过程,因此可能出现副作用;

7、现代 C++ 编译器对内联函数的行为:

  • 现代 C++ 编译器能够进行编译优化,一些函数即使没有 inline 声明,也可能被内联编译;
    内联函数可能被拒绝是因为 C++ 诞生年代相对于现在比较早,当时编译 技术未有达到现在先进的技术,因此对于一些复杂的内联函数,C++ 编译器没有能力将函数体直接扩展到调用的地方,所以 inline 关键字在当时设计成了对编译器的请求;
  • 一些现代 C++ 编译器提供了扩展语法,能够对函数进行强制内联,如:
    g++:__attribute__((always_inline)) 属性;
    不是标准 C++ 属性;
    MAVC:__forceinline;

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

  • main.cpp 文件:


[code]#include

__forceinline
// __attribute__((always_inline))
// inline
int add_inline(int n);

int main(int argc, char *argv[])
{
    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
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:200
帖子:40
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP