zoukankan      html  css  js  c++  java
  • 第6课 内联函数分析

    1. const常量宏常量回顾

    (1)C++中的const常量可以替代宏常数定义,如:

            const int A = 3; ←→ #define A  3

    (2)C++中是否有解决方案,可以用来替代宏代码片段呢?

    2. 内联函数

    2.1 内联函数的定义

    (1)C++编译器可以将一个函数进行内联编译,被C++编译器内联编译函数内联函数

    (2)C++中使用inline关键字声明内联函数

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

    (3)内联函数声明inline关键字必须和函数定义结合在一起否则编译器会直接忽略内联请求。(注释:经测试在vs2013下,inline放在声明或定义前均可以

    2.2 内联函数的特点

    (1)C++编译器接将内联函数函数体插入到函数调用的地方

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

    (3)C++中推荐使用内联函数替代宏代码片段。

    (4)C++编译器不一定满足函数的内联请求

    【编程实验】内联函数初探  6-1.cpp

    #include <stdio.h>
    
     
    
    #define FUNC(a, b) ((a) < (b) ? (a) : (b))
    
     
    
    //MSVC下:要让inline、__forceinline生效必须得做如下的设置:
    
    //①在“项目”→“配置属性”→“C / C++” →“优化”→“内联函数扩展”中选择“只适用于__inline(/ Ob1)”
    
    //②在“配置属性”→“C / C++” →“所有选项”→“调试信息格式”中选择“程序数据库( / Zi)”
    
     
    
    inline int func(int a, int b) //VS2013下,inline可放在声明前或也可放在定义前。或两者前都加
    
    {
    
        return a < b ? a : b;
    
    }
    
     
    
    int main()
    {
    
        int a = 1;
    
        int b = 3;
    
     
    
        /*
    
        int c = FUNC(++a, b);//相当于(++a)<(b)?:(++a):(b);
    
     
    
        printf("a = %d
    ", a); //3
    
        printf("b = %d
    ", b); //3
    
        printf("c = %d
    ", c); //3
    
     
    
        */
    
     
    
        int c = func(++a, b);
    
     
    
        printf("a = %d
    ", a);     //2
    
        printf("b = %d
    ", b); //3
    
        printf("c = %d
    ", c);     //2
    
     
    
        return 0;
    
    }

    运行结果:

              

        左图:内联函数没嵌入到调用地方(仍为函数调用)                                  右图:函数体被嵌入到调用的地方              

    2.3 内联函数与宏的不同

     

    宏代码片段

    内联函数

    处理方式

    预处理器处理,只是进行简单的文本替换

    编译器处理,会将函数体嵌入到调用的地方

    但内联请求也可能被编译器拒绝

    类型检查

    不做类型检查

    具有普通函数的特征,会进行参数和返回类型的检查

    副作用

    2.4 现代C++编译器对内联函数的优化

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

    (2)一些现代的C++编译器提供了扩展语法,可用下列关键字替代inline来对函数进行强制内联,如:

    g++__atrribute__((always_inline))

    MSVC__forceinline

    (3)MSVC下:要让inline__forceinline生效必须得做如下的设置

      ①在“项目”→“配置属性”→“C/C++” →“优化”→“内联函数扩展”中选择“只适用于__inline(/Ob1)”

      ②在“配置属性”→“C/C++” →“所有选项”→“调试信息格式”中选择“程序数据库(/Zi)”

    【编程实验】内联函数深度示例  6-2.cpp

    #include <stdio.h>
    
    
    
    //MSVC2013下:在函数声明或定义前加inline或__forceinline都可以
    
    //同时,这两个的表现行为几乎一模一样。只不过__forceinline是MS
    
    //下的,而inline是标准C++的,可移植性更高。
    
    
    
    //__forceinline
    
    //__attribute__((always_inline))
    
    //inline
    
    int add_inline(int n);
    
    
    
    int main()
    
    {
    
        int r = add_inline(10);
    
    
    
        printf("r = %d
    ", r);
    
    
    
        return 0;
    
    }
    
    
    
    __forceinline int add_inline(int n)
    
    {
    
        int ret = 0;
    
    
    
        for (int i = 0; i < n; i++)
    
        {
    
            ret += i;
    
        }
    
    
    
        return ret;
    
    }

    运行结果:

      

    3. C++中inline内联编译的限制

    (1)含有递归调用的函数不能设置为inline

    (2)使用了复杂流程控制语句循环语句switch语句,无法设置为inline。不能存在过多的条件判断语句(说明:如上述实例,在VS2013下,循环语句是可以被内联的)

    (3)函数体不能过于庞大

    (4)不能对函数进行取址操作

    (5)函数内联声明必须在调用语句之前

    4. 小结

    (1)C++中可以通过inline声明内联函数

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

    (3)inline只是一种请求编译器不一定允许这种请求

    (4)内联函数省去了函数调用时压栈、跳转和返回的开销

    (5)const 常量<--->宏常量

        内联函数<------>宏代码

  • 相关阅读:
    Python3学习之路~0 目录
    HIVE简单操作
    HIVE的安装
    mysql在linux上的安装
    BZOJ 1085(IDA*)
    Codeforces 916E(思维+dfs序+线段树+LCA)
    Codeforces 396C (DFS序+线段树)
    Codeforces 609E (Kruskal求最小生成树+树上倍增求LCA)
    Codeforces 191C (LCA+树上差分算法)
    POJ 1905 题解(二分+几何)
  • 原文地址:https://www.cnblogs.com/hoiday/p/10087907.html
Copyright © 2011-2022 走看看