zoukankan      html  css  js  c++  java
  • inline内联函数

    c程序执行过程就是不同函数互相调用的过程,但是函数调用是有时间和空间开销的,函数调用需要执行入栈出栈操作。如果函数很复杂,执行时间长,那么入栈出栈的操作相比之下可以忽略,但如果函数较简单,那么相比之下入栈出栈的开销就不能忽略了。因此c++提供了一种代码替换的方法,就是内联函数inline。在编译时用函数体替换调用语句,类似于宏定义。又称为内置函数。

    #include <iostream>
    using namespace std;
    //内联函数,交换两个数的值
    inline void swap(int *a, int *b){
        int temp;
        temp = *a;
        *a = *b;
        *b = temp;
    }
    int main(){
        int m, n;
        cin>>m>>n;
        cout<<m<<", "<<n<<endl;
        swap(&m, &n);
        cout<<m<<", "<<n<<endl;
        return 0;
    }

    内联函数的定义和声明要写在一起,不推荐下面分开的写法

    #include <iostream>
    using namespace std;
    //声明内联函数
    void swap1(int *a, int *b);  //也可以添加inline,但编译器会忽略
    int main(){
        int m, n;
        cin>>m>>n;
        cout<<m<<", "<<n<<endl;
        swap1(&m, &n);
        cout<<m<<", "<<n<<endl;
        return 0;
    }
    //定义内联函数
    inline void swap1(int *a, int *b){
        int temp;
        temp = *a;
        *a = *b;
        *b = temp;
    }

    内联函数的缺点很明显,编译后程序中会存在多分相同函数的拷贝,如果内联函数比较大,那么编译后的程序体积也会很大,所以内联函数一般都是那些短小且调用频繁的函数。

    内联函数不是强制性的,对函数做inline声明只是程序员对编译器提出的一个建议,编译过程中并不一定会百分百进行函数体替换。

    相比与宏定义,内联函数更安全,宏定义只是字符替换,并没有参数检查,而函数是有参数检查的,而且宏定义很容易因为优先级的问题踩坑,写的时候需要很小心,但是内联函数相比之下就不用那么费心。

    #include <iostream>
    using namespace std;
    #define SQ(y) y*y
    int main(){
        int n, sq;
        cin>>n;
        sq = SQ(n+1);
        cout<<sq<<endl;
        return 0;
    }

    宏被替换成了n+1*n+1,优先级错误,所以应该改为#define SQ(y) (y)*(y)

    #include <iostream>
    using namespace std;
    #define SQ(y) (y)*(y)
    int main(){
        int n, sq;
        cin>>n;
        sq = 200 / SQ(n+1);
        cout<<sq<<endl;
        return 0;
    }

    这次宏被替换成了200/(n+1)*(n+1),同样出现了优先级错误,所以要改成#define SQ(y) ((y)*(y))

    就很心累,但如果用内联函数来写的话就轻松很多了

    #include <iostream>
    using namespace std;
    inline int SQ(int y){ return y*y; }
    int main(){
        int n, sq;
        cin>>n;
        //SQ(n)
        sq = SQ(n);
        cout<<sq<<endl;
        //SQ(n+1)
        sq = SQ(n+1);
        cout<<sq<<endl;
        //200 / SQ(n+1)
        sq = 200 / SQ(n+1);
        cout<<sq<<endl;
        return 0;
    }

    宏定义是在预处理阶段展开,内联函数是在编译时展开,这也是两者的一个区别

    内联函数的编写规范

    内联函数不应该有函数声明,要把内联函数定义在它应该声明的地方。

    再多文件编程中,经常把函数的定义放在源文件中,把函数的声明放在头文件中,这样调用函数时只要引入头文件即可,这种将函数定义和生命分开的做法是正确的,但是并不适用于内联函数,内联函数的定义和生命分散到不同文件中会出现错误。

    main.cc

    #include <iostream>
    using namespace std;
    //内联函数声明
    void func();
    int main(){
        func();
        return 0;
    }

    module.cc

    #include <iostream>
    using namespace std;
    //内联函数定义
    inline void func(){
        cout<<"inline function"<<endl;
    }

    代码可以通过编译,但是连接时会出错,因为内联函数在编译时会展开,替换,编译完成后内联函数就不存在了,所以链接的时候就会找不到函数的定义。

    函数的本质是一段复用的代码,存在于虚拟内存的代码区中,也占有可执行文件的一部分体积。内联函数虽然语法和函数一样,但他再编译后从虚拟内存的代码区中消除了。

    因此从代码复用的角度来讲,内联函数已经不算是函数了,内联函数更像是宏定义的一个替换方案,而不是当作一个正常函数来使用。

    多文件编程时直接在头文件中定义内联函数,不要把定义和声明分开。

    无情的摸鱼机器
  • 相关阅读:
    go语言入门(3)运算符及流程控制
    go语言入门(2)数据类型
    go语言入门(1)
    ubuntu上软件下载慢,github下载慢
    密码基础知识(2)以RSA为例说明加密、解密、签名、验签
    让你减少焦虑的一首英文小诗
    使用脚本启动fabric时出错
    Hyperledger Fabric(5)ChainCode的编写步骤
    Hyperledger Fabric(4)链码ChainCode
    设计题专题总结
  • 原文地址:https://www.cnblogs.com/wangtianning1223/p/14850306.html
Copyright © 2011-2022 走看看