精华内容
下载资源
问答
  • inline 内联函数

    2020-03-09 11:39:22
    inline 内联函数 特征 相当于把内联函数里面的内容写在调用内联函数处; 相当于不用执行进入函数的步骤,直接执行函数体; 相当于宏,却比宏多了类型检查,真正具有函数特性; 编译器一般不内联包含循环、递归、...

    inline 内联函数

    特征

    相当于把内联函数里面的内容写在调用内联函数处;
    相当于不用执行进入函数的步骤,直接执行函数体;
    相当于宏,却比宏多了类型检查,真正具有函数特性;
    编译器一般不内联包含循环、递归、switch 等复杂操作的内联函数;
    在类声明中定义的函数,除了虚函数的其他函数都会自动隐式地当成内联函数。
    

    inline 使用

    // 声明1(加 inline,建议使用)
    inline int functionName(int first, int second,...);
    
    // 声明2(不加 inline)
    int functionName(int first, int second,...);
    
    // 定义
    inline int functionName(int first, int second,...) {/****/};
    
    // 类内定义,隐式内联
    class A {
        int doA() { return 0; }         // 隐式内联
    }
    
    // 类外定义,需要显式内联
    class A {
        int doA();
    }
    inline int A::doA() { return 0; }   // 需要显式内联
    

    编译器对 inline 函数的处理步骤

    将 inline 函数体复制到 inline 函数调用点处;
    为所用 inline 函数中的局部变量分配内存空间;
    将 inline 函数的的输入参数和返回值映射到调用方法的局部变量空间中;
    如果 inline 函数有多个返回点,将其转变为 inline 函数代码块末尾的分支(使用 GOTO)。
    

    优缺点

    优点

    内联函数同宏函数一样将在被调用处进行代码展开,省去了参数压栈、栈帧开辟与回收,结果返回等,从而提高程序运行速度。
    内联函数相比宏函数来说,在代码展开时,会做安全检查或自动类型转换(同普通函数),而宏定义则不会。
    在类中声明同时定义的成员函数,自动转化为内联函数,因此内联函数可以访问类的成员变量,宏定义则不能。
    内联函数在运行时可调试,而宏定义不可以。
    

    缺点

    代码膨胀。内联是以代码膨胀(复制)为代价,消除函数调用带来的开销。如果执行函数体内代码的时间,相比于函数调用的开销较大,那么效率的收获会很少。另一方面,每一处内联函数的调用都要复制代码,将使程序的总代码量增大,消耗更多的内存空间。
    inline 函数无法随着函数库升级而升级。inline函数的改变需要重新编译,不像 non-inline 可以直接链接。
    是否内联,程序员不可控。内联函数只是对编译器的建议,是否对函数内联,决定权在于编译器。
    

    虚函数(virtual)可以是内联函数(inline)

    虚函数可以是内联函数,内联是可以修饰虚函数的,但是当虚函数表现多态性的时候不能内联。
    内联是在编译器建议编译器内联,而虚函数的多态性在运行期,编译器无法知道运行期调用哪个代码,因此虚函数表现为多态性时(运行期)不可以内联。
    inline virtual 唯一可以内联的时候是:编译器知道所调用的对象是哪个类(如 Base::who()),这只有在编译器具有实际对象而不是对象的指针或引用时才会发生。
    

    虚函数内联使用

    #include <iostream>  
    using namespace std;
    class Base
    {
    public:
        inline virtual void who()
        {
            cout << "I am Base\n";
        }
        virtual ~Base() {}
    };
    class Derived : public Base
    {
    public:
        inline void who()  // 不写inline时隐式内联
        {
            cout << "I am Derived\n";
        }
    };
    
    int main()
    {
        // 此处的虚函数 who(),是通过类(Base)的具体对象(b)来调用的,编译期间就能确定了,所以它可以是内联的,但最终是否内联取决于编译器。 
        Base b;
        b.who();
    
        // 此处的虚函数是通过指针调用的,呈现多态性,需要在运行时期间才能确定,所以不能为内联。  
        Base *ptr = new Derived();
        ptr->who();
    
        // 因为Base有虚析构函数(virtual ~Base() {}),所以 delete 时,会先调用派生类(Derived)析构函数,再调用基类(Base)析构函数,防止内存泄漏。
        delete ptr;
        ptr = nullptr;
    
        system("pause");
        return 0;
    } 
    

    在这里插入图片描述
    可以看到结果,第二次调用的who()函数为派生类Derived中的who()函数,是在运行时确定的。

    展开全文
  • inline内联函数

    2019-09-10 22:02:16
    inline内联函数 适用于:频繁调用的短小函数 (因为频繁调用会大量消耗栈空间) 用来代替c语言中 表达式形式 的宏定义 inline定义的类的内联函数,在使用时直接进行替换(像宏一样展开),没有了调用的开销,效率...

    inline内联函数

    适用于:频繁调用的短小函数 (因为频繁调用会大量消耗栈空间)

    特点:安全、提高效率、但以消耗空间为代价

    用来代替c语言中 表达式形式 的宏定义

    inline定义的类的内联函数,在使用时直接进行替换(像宏一样展开),没有了调用的开销(函数的压栈退栈),效率也很高。

    #include <stdio.h>
    //函数定义为inline即:内联函数
    inline char* dbtest(int a)
     {
        return (i % 2 > 0) ? "奇" : "偶";
    } 
     
    int main()
    {
       int i = 0;
       for (i=1; i < 100; i++)
        {
           printf("i:%d    奇偶性:%s /n", i, dbtest(i));    //不调用dbtest函数,而是用函数体直接替换函数调用
       }
    }
    

    调用 dbtest(i) 的地方都替换成了 (i%2>0)?“奇”:“偶”,这样就避免了频繁调用函数对栈内存重复开辟所带来的消耗。

    内联函数和宏定义的区别

    内联函数 宏定义
    本质是函数,在编译的时候编译器会在调用内联函数的地方直接把函数体插入(可以省去函数压栈退栈的时间),提高效率 宏不是函数,只是在预编译阶段把宏名用宏体代替(简单的字符串替换
    在编译的时候会进行参数类型的检查 不检查
    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,663
精华内容 1,865
关键字:

inline内联函数