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

    1.  常量与宏回顾

    (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++编译器也不一定满足函数的内联请求

    【编程实验】内联函数初探

                        

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

    #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 内联函数与宏的不同

    内联函数

    处理方式

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

    编译器处理,会将函数体嵌入到调用的地方。但内联请求也可能被编译器拒绝

    类型检查

    不做类型检查

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

    副作用

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

    #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;
    }

    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)”

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

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

    (2)使用了复杂流程控制语句:循环语句和switch语句,无法设置为inline(说明:如上述实例,在VS2013下,循环语句是可以被内联的)

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

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

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

    4. 小结

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

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

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

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

  • 相关阅读:
    Java核心技术 卷一 笔记四 库类的直接使用
    Java核心技术 卷一 笔记三 大数值及数组
    Java核心技术 卷一 笔记2 字符串的复制
    Java核心技术 卷一 笔记1
    修改css 样式后, hover事件 不生效
    修改 element ui input 输入框 样式不生效问题
    css3 计算属性
    Vue3 改动系列
    浏览器实现,向下滑动 鼠标滚轮,页面横向移动
    linux ceont0s7 vue 打包压缩图片 一直报错
  • 原文地址:https://www.cnblogs.com/5iedu/p/5372171.html
Copyright © 2011-2022 走看看