精华内容
下载资源
问答
  • 内联函数和宏定义函数的区别

    千次阅读 2019-05-17 19:53:55
    1、不同点: 内联函数是在编译时展开,而宏在预编译时展开;在编译的时候,内联函数直接被嵌入到目标代码中去,而宏只是一个简单的文本替换。 ... inline有点类似于宏定义,但是它和宏定义不同...

    1、不同点:

    • 内联函数是在编译时展开,而宏在预编译时展开;在编译的时候,内联函数直接被嵌入到目标代码中去,而宏只是一个简单的文本替换。
    • 内联函数可以进行诸如类型安全检查、语句是否正确等编译功能,宏不具有这样的功能;宏不是函数,而inline是函数。
    • 宏在定义时要小心处理宏参数,一般用括号括起来,否则容易出现二义性。而内联函数不会出现二义性。
    • inline有点类似于宏定义,但是它和宏定义不同的是,宏定义只是简单的文本替换,是在预编译阶段进行的。而inline的引入正是为了取消这种复杂的宏定义的。

    2、举例:

    • 宏定义:
    #define MAX(a,b) ((a)>(b)?(a):(b))
    MAX(a,"Hello"); //错误地比较int和字符串,没有参数类型检查
    • 内联函数:
    #include <stdio.h>
     
    inline int add(int a, int b)
    {
        return (a + b);
    }
    
    int main(void)
    {
        int a;
    
        a = add(1, 2);
        printf("a+b=%d\n", a);
    
        return 0;
    }
    以上a = add(1, 2);处在编译时将被展开为:
    a = (a + b);

    3、使用时的一些注意事项:

    • 使用宏定义一定要注意错误情况的出现,比如宏定义函数没有类型检查,可能传进来任意类型,从而带来错误,如举例。还有就是括号的使用,宏在定义时要小心处理宏参数,一般用括号括起来,否则容易出现二义性
    • inline函数一般用于比较小的,频繁调用的函数,这样可以减少函数调用带来的开销。只需要在函数返回类型前加上关键字inline,即可将函数指定为inline函数。
    • 同其它函数不同的是,最好将inline函数定义在头文件,而不仅仅是声明,因为编译器在处理inline函数时,需要在调用点内联展开该函数,所以仅需要函数声明是不够的。

    4、内联函数使用的条件:

    • 内联是以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率。如果执行函数体内代码的时间,相比于函数调用的开销较大,那么效率 的收获会很少。另一方面,每一处内联函数的调用都要复制代码,将使程序的总代码量增大,消耗更多的内存空间。以下情况不宜使用内联: 
    • (1)如果函数体内的代码比较长,使用内联将导致内存消耗代价较高。 
    • (2)如果函数体内出现循环,那么执行函数体内代码的时间要比函数调用的开销大。 
    • 内联不是什么时候都能展开的,一个好的编译器将会根据函数的定义体,自动地取消不符合要求的内联。

    5、使用内联函数和宏函数可能带来的问题(慎用):

    • 有时不要仅是为了提高编程效率而使用这两种函数,要综合考虑后再使用,因为有时使用这两种函数可能带来其他的问题,比如出现问题不能使用gdb调试问题,内联函数不展开,宏函数没有参数检测等

     

     

    展开全文
  • 内联函数和宏定义

    2021-09-29 08:07:30
    1.内联函数和宏定义的区别 内联函数和普通函数相比可以加快程序的运行速度,在编译的时候内联函数可以直接镶嵌到目标代码中,而宏只是一个不加任何检查的简单的替换。内联函数要做参数类型检查。宏不是函数,只是在...

    1.内联函数和宏定义的区别

    内联函数和普通函数相比可以加快程序的运行速度,在编译的时候内联函数可以直接镶嵌到目标代码中,而宏只是一个不加任何检查的简单的替换。内联函数要做参数类型检查。宏不是函数,只是在编译预处理阶段将程序中的有关字符串替换成宏体。
    inline是嵌入代码,在调用函数的地方直接把代码写到这个地方,而不用中断调用。对于短小的代码来说,inline增加空间消耗,换时间效率,也就是我们常说的空间换时间。但是inline需要根据具体情况来选择是否需要使用。

    2.内联函数的使用情况

    内联函数一般用于以下情况
    (1)一个函数不断被重复调用
    (2)函数只有简单的几行代码,且不应该包含for,while,switch这些语句
    一般小程序不需要使用内联函数,如果完成一个大的工程项目,且一个简单的函数被调用多次,那么可以考虑使用。
    关键字inline必须与函数定义放在一起才能使函数成为内联函数,比如

    inline void fun();
    void fun(){}
    

    如上面这种情况就起不到作用。
    再比如

    void fun();
    inline void fun(){}
    

    上面这种情况才会起到作用。
    在书籍中有提出,宏是用于"实现的关键字"而不是用于“声明的关键字”。

    3.内联函数不宜使用的情况

    那么不禁提出问题,既然内联函数可以提高效率,为什么不都使用内联函数呢?
    原因是内联是以代码膨胀(复制)为代价,省去函数调用的开销,从而提高函数的执行效率。如果执行函数体内的代码的时间远远比函数调用开销大,那么使用内敛函数效益会很小,这时候牺牲空间换时间就显得不值当了。另外,每处都尽可能使用内联函数的话,将使程序的代码量变大,多消耗很多空间。
    以下情况不宜使用内联
    (1)如果函数体内的代码较长,使用内联会导致消耗较多空间。
    (2)如果函数体内出现循环,执行函数体内代码的开销要比调用函数开销大。
    一个好编译器会自动取消不合理的内联。

    展开全文
  • C/C++中的内联函数和宏定义区别

    千次阅读 2016-10-26 16:52:53
    内联函数和宏的区别在于,是由预处理器对进行替代,而内联函数是通过编译器控制来实现的。而且内联函数是真正的函数,只是在需要用到的时候,内联函数一样的展开,所以取消了函数的参数压栈,减少了调用的...

    内联函数和宏定义

    前段时间被面试问了内联函数作用,一直只模糊知道就是提高效率,回来仔细看了书,很多细节需要注意。在说内联函数之前,必须理解预处理宏。内联函数的功能和预处理宏的功能相似但也有不同。

     

    一.宏定义的优点与缺陷:

    之所以用宏定义:因为函数的调用必须要将程序执行的顺序转移到函数所存放在内存中的某个地址,将函数的程序内容执行完后,再返回到转去执行该函数前的地方。这种转移操作要求在转去执行前要保存现场并记忆执行的地址,转回后要恢复现场,并按原来保存地址继续执行。因此,函数调用要有一定的时间和空间方面的开销,于是将影响其效率。

    宏只是在预处理的地方把代码展开,不需要额外的空间和时间方面的开销,所以调用一个宏比调用一个函数更有效率
      但是宏也有缺陷:
    1、宏不能访问对象的私有成员。
    2、宏的定义很容易产生二义性。(容易出错)
    举个例子,宏定义一个乘法函数:   #define multi(x) (x*x)

    先用multi(10)这样调用看上去没有什么错误,结果返回100,是正确的,但是如果用multi(10+10)去调用的话,我们期望的结果是400,而宏的调用结果是(10+10*10+10),结果是120,这显然不是我们要得到的结果。避免这些错误的方法,一般是给宏的参数都加上括号。如是:  #define multi(x) ((x)*(x))

    这样可以确保不会出现上面那样的错,但是,即使使用括号这种定义,这个宏依然有可能出错,例如使用multi(a++)调用它,我们期望得到(a+1)*(a+1)的结果,而实际宏的展开结果: (a++)*(a++),如果a的值是4,我们得到的结果是5*6=30。而我们期望的结果是5*5=25,这又出现了问题,++执行了两次。

    这些宏定义难以避免的问题,我们可以用内联函数来,用内联函数来取代宏定义。


    二.内联函数的优点及声明使用

    内联函数和宏的区别在于,宏是由预处理器对宏进行替代,而内联函数是通过编译器控制来实现的。而且内联函数是真正的函数,只是在需要用到的时候,内联函数像宏一样的展开,所以取消了函数的参数压栈,减少了调用的开销。你可以象调用函数一样来调用内联函数,而不必担心会产生于处理宏的一些问题。(但节约时间的同时增加了空间的消耗)

     

    我们用inline来定义内联函数,在C++中,在类的声明部分定义了函数体的函数,被默认为是内联函数。而不管你是否有inline关键字。(不过编译器会决定要不要将它内联)。我们也可以将定义在类的外部的函数定义为内联函数。内联函数必须是和函数体申明在一起才有效。像这样的申明inlinefunction(int i)是无效的,编译器只是把函数作为普通的函数申明,我们必须定义函数体。

    例如: inlinefunction(inti ) {return i*i };

    这样才算定义了一个内联函数。我们可以把它作为一般的函数一样调用。但是执行速度确比一般函数的执行速度要快。
       内联函数主要分成两种,一种是类成员内部的内联函数,一种是类外面的全局内联函数:

    1.类内部的内联函数:在C++的类成员中,如果成员函数的函数体本身结构不复杂,代码量也较少的时候,直接在定义这个函数的时候就完成该函数的实现,这样的一个过程在C++类中会被默认当做内联函数。

    2.类外部的内联函数,当将一个全局函数定义成内联函数的时候,需要加一个inline 的关键字说明,相当于告诉编译器建议将该函数当内联函数进行处理。

    注意:inline关键字仅仅是建议编译器做内联展开处理,而不是强制。被"inline"修饰的函数不一定被内联(但是无"inline"修饰的函数一定不是,类内部函数一定是)。而且内联使用不恰当是会有副作用的,会带来代码膨胀,还有可能引入难以发现的程序问题。如果内联函数的函数体过大,一般的编译器会放弃内联方式,而采用普通的方式调用函数。这样,内联函数就和普通函数执行效率一样了。


    三.内联函数需要注意和不能内联的情况

    使用内联函数的主要作用是减少函数调用引起的过多的内存消耗,在使用内联函数中应当要注意

    1.      在定义内联函数应当尽量定义成那些调用非常频繁而且函数功能简单的函数,而不能将函数实现很复杂的功能定义成内联

    2.      由于内联函数在调用的时候直接暴露出了函数体,故会造成泄漏函数功能的现象

    3.      在内联函数中尽量减少变量的申请,尽量简化内联函数的函数体,这也对程序结构有好处

    4.      因为内联函数要在调用处展开,编译器必须能在每一个调用处能看到该函数的定义,因此最好将函数实现放在头文件中

    5.      在实现文件中该函数之前要加上inline关键字的方式是有问题的:如果调用的obj文件在函数定义之前生成,那么该处就无法嵌入内联函数了。

     

    以下不会被内联的几种情况:    

    1.包含了递归、循环等结构的函数一般不会被内联。

    2.虚拟函数一般不会内联,但是如果编译器能在编译时确定具体的调用函数,那么仍然会就地展开该函数。

    3.如果通过函数指针调用内联函数,那么该函数将不会内联而是通过call进行调用。

    4.构造和析构函数一般会生成大量代码,因此一般也不适合内联。

    5.如果内联函数调用了其他函数也不会被内联。

     


    四. 内联函数和宏定义的比较

    总结内联函数和宏定义的不同:

    1.       内联函数在运行时可调试,而宏定义不可以;

    2.       编译器会对内联函数的参数类型做安全检查或自动类型转换(同普通函数),而宏定义则不会; 

    3.       内联函数可以访问类的成员变量,宏定义则不能; 

    C++ 语言支持函数内联,其目的是为了提高函数的执行效率(速度)。 而在C程序中,可以用宏代码提高执行效率。宏代码本身不是函数,但使用起来象函数。预处理器用复制宏代码的方式代替函数调用,省去了参数压栈、生成汇编语言的 CALL调用、返回参数、执行return等过程,从而提高了速度。使用宏代码最大的缺点是容易出错,预处理器在复制宏代码时常常产生意想不到的边际效应。当使用内联函数的时候,起目的是为了消除函数调用上的开销,频繁的调用函数会增加内存上的开销。通过一个内联函数可以得到所有宏的替换效能和所有可预见的状态以及常规函数的类型检查。

     

    这篇文章http://www.cnblogs.com/xkfz007/articles/2370640.html  详细说了static inline 和 externinline的用法以及gcc 和c99里的inline的区别。摘了点:

    static inline可以认为是一个static的函数,加上了inline的属性。这个函数大部分表现和普通的static函数一样,只不过在调用这种函数的时候,gcc会在其调用处将其汇编码展开编译而不为这个函数生成独立的汇编码。除了以下几种情况外:
    (1)函数的地址被使用的时候。如通过函数指针对函数进行了间接调用。这种情况下就不得不为static inline函数生成独立的汇编码,否则它没有自己的地址。
    (2)其他一些无法展开的情况,比如函数本身有递归调用自身的行为等。
    static inline函数和static函数一样,其定义的范围是local的,即可以在程序内有多个同名的定义(只要不位于同一个文件内即可)。
    (3)gcc的static inline函数仅能作用于文件范围内;c的inline函数是全局性的:在文件内可以作为一个内联函数被内联展开,而在文件外可以调用它。

    而 externinline的函数只会被内联进去,而绝对不会生成独立的汇编码!另外,extern inline的函数允许和外部函数重名,即在存在一个外部定义的全局库函数的情况下,再定义一个同名的extern inline函数也是合法的。

    extern inline的用法。第一:它可以表现得像宏一样,可以在文件内用extern inline版本的定义取代外部定义的库函数(前提是文件内对其的调用不能出现无法内联的情况);第二:它可以让一个库函数在能够被内联的时候尽量被内联使用。
    注意:gcc绝对不会为extern inline的函数生成独立汇编码。

     



     


    展开全文
  • 内联函数和宏定义的区别内联函数定义用法宏定义定义用法内联函数和宏定义的区别以及使用场景内联函数内联函数优点内联函数缺点宏定义宏定义优点宏定义缺点使用场景补充:C++中函数调用机制 内联函数 定义 某度百科中...

    内联函数

    定义

    某度百科中对内联函数是这样定义的:内联函数(有时称作在线函数或编译时期展开函数)是一种编程语言结构,用来建议编译器对一些特殊函数进行内联扩展(有时称作在线扩展)。

    由其定义我们可以看出,内联函数其本质是一个函数, 只不过其调用方式和普通函数有区别而已。普通函数在编译时期是通过函数调用机制(下面会简单讲到)对其进行调用,而内联函数是通过将函数体直接插入调用处来实现的,这样可以大大减少由函数调用带来的开销,从而提高程序的运行效率。

    用法

    一般来说inline用于定义类的成员函数。
    对于一个类来说,其成员函数有两种定义的方式:一种是在类内定义和声明,一种是在类内声明,类外定义。具体如下:

    • 类内定义和声明
    class A
    {
        A(){}
        void func()
        {
            cout << "hello" << endl;
        }
        ~A(){}
    };
    
    • 类内声明,类外定义
    class A
    {
        A();
        void func();
        ~A();
    };
    
    A::A()
    {
        cout << "A::A()" << endl;
    }
    
    void A::func()
    {
        cout << "A::func()" << endl;
    }
    A::~A()
    {
        cout << "A::~A()" << endl;
    }
    

    其中类内定义和声明的成员函数默认是内联函数。 对于类内声明类外定义的成员函数来说,需要在声明或者定义处(或两处同时)加上inline关键字才能声明为内联函数。

    如下:

    class A
    {
        inline A(); // 声明处添加inline关键字
        void func();// 定义处添加inline关键字
        inline ~A();// 声明处和定义处添加inline关键字
    };
    
    A::A()
    {
        cout << "A::A()" << endl;
    }
    
    inline void A::func()
    {
        cout << "A::func()" << endl;
    }
    inline A::~A()
    {
        cout << "A::~A()" << endl;
    }
    

    宏定义

    定义

    宏定义在 C 语言源程序中允许用一个标识符来表示一个字符串,称为“宏/宏体” ,被定义为“宏”的标识符称为“宏名”。在编译预处理时,对程序中所有出现的宏名,都用宏定义中的字符串去代换,这称为“宏替换”或“宏展开”。 宏定义是由源程序中的宏定义命令完成的,宏代换是由预处理程序自动完成的。

    由其定义我们可以看出,宏定义本质是未字符串取了一个简单的别名, 当程序中要使用某个比较复杂的原字符串的时候就可以用简单的别名把它替换掉。

    用法

    在 C 语言中,宏分为 有参数和无参数两种。

    • 无参宏的宏名后不带参数,其定义和使用的一般形式为:
    #include <iostream>
    
    #define M "hello word" // 无参数宏定义
    #define MAX 10 //无参数宏定义
    
    using namespace std;
    
    
    int main()
    {
        cout << M << endl; // 无参数宏使用
        cout << MAX << endl; // 无参数宏使用
        return 0;
    }
    

    有参宏的宏名后带参数,其定义和使用的一般形式为:

    #include <iostream>
    
    #define M(y) (y)*3+(y)*3 // 有参数宏定义
    
    using namespace std;
    
    int main()
    {
        cout << M(5) << endl;
        return 0;
    }
    

    内联函数和宏定义的区别以及使用场景

    内联函数

    内联函数优点

    • inline 定义的类的内联函数,函数的代码被放入符号表中,在使用时直接进行替换,(像宏一样展开),没有了调用的开销,效率也很高。
    • 类的内联函数也是一个真正的函数,编译器在调用一个内联函数时,会首先检查它的参数的类型,保证调用正确。然后进行一系列的相关检查,就像对待任何一个真正的函数一样。这样就消除了它的隐患和局限性。
    • inline函数可以作为一个类的成员函数,与类的普通成员函数作用相同,可以访问一个类的私有成员和保护成员。内联函数可以用于替代一般的宏定义,最重要的应用在于类的存取函数的定义上面。

    内联函数缺点

    • 内联函数的函数体一般来说不能太大,如果内联函数的函数体过大,一般的编译器会放弃内联方式,而采用普通的方式调用函数。

    宏定义

    宏定义优点

    • 方便程序的修改。使用简单宏定义可用宏代替一个在程序中经常使用的常量,这样在将该常量改变时,不用对整个程序进行修改,只修改宏定义的字符串即可,而且当常量比较长时, 我们可以用较短的有意义的标识符来写程序,这样更方便一些。

    宏定义缺点

    • 嵌套定义过多可能会影响程序的可读性,而且很容易出错,不容易调试。
    • 对带参的宏而言,由于是直接替换,并不会检查参数是否合法,存在安全隐患。

    使用场景

    • 一般来说,用宏来代表简短的表达式比较合适。
    • 还有一些任务根本无法用函数实现,但是用宏定义却很好实现。比如参数类型没法作为参数传递给函数,但是可以把参数类型传递给带参的宏。
    • C++的inline的提出就是为了完全取代宏定义,因为inline函数取消了宏定义的缺点,又很好地继承了宏定义的优点。
    • 内联函数一般用于类的成员函数,且函数体比较简单的情况下(不包含复杂的控制语句,如循环,switch等)。

    补充:C++中函数调用机制

    一般来说,当任何一个函数调用发生时,系统都要作以下工作:

    (1)建立栈空间;
    (2)保护现场:主调函数运行状态和返回地址入栈;
    (3)为被调函数中的局部变量分配空间,完成参数传递;
    (4)执行被调函数函数体;
    (5)释放被调函数中局部变量占用的栈空间;
    (6)回复现场:取主调函数运行状态及返回地址,释放栈空间;
    (7)继续主调函数后续语句。

    展开全文
  • 1.内联函数在运行时可调试,而宏定义不可以; 2.编译器会对内联函数的参数类型做安全检查或自动类型转换(同普通函数),而宏定 义则不会; 3.内联函数可以访问类的成员变量,宏定义则不能; 4.在类中声明同时定义...
  • 内联函数和宏定义的总结

    千次阅读 2016-03-30 23:18:03
    内联(inline)函数,不同于普通函数的是:普通函数是在编译是调用者分别编译,运行到调用处时,...内联函数的优点:节省时间,减少了运行时函数调用的时间开销(参数值传递,主调函数被调函数运行栈的切换)。
  • 内联函数在运行时可调试,而宏定义不可以;2.编译器会对内联函数的参数类型做安全检查或自动类型转换(同普通函数),而宏定义则不会; 3.内联函数可以访问类的成员变量,宏定义则不能; 4.在类中声明同时定义的成员...
  • 内联函数宏定义

    2019-09-27 12:22:07
    2、内联函数声明必须和定义一起,如果只有声明,编译器只会将它看做普通函数的声明,如果声明的时候使用inline,定义在其他地方也用inline,那么它是内联还是普通函数:普通函数。查汇编代码,内联函数与普通函数...
  • 宏定义 #define f(x) x * x 宏定义由预处理器处理。如上示例,在程序编译前,预处理器把代码中的所有 f(x) 替换成 x * x 。 宏定义避免了像普通函数一样,申请内存栈,保留现场指针...内联函数 // 不作为成员函数的
  • 原文地址:http://www.programmerinterview.com/index.php/c-cplusplus/inline-vs-macro/ 转载地址:... 这个问题在苹果公司(Apple)直觉(Intuit)公司面试时都有问到。 ...内联函数和
  • 内联函数和普通函数相比可以加快程序运行的速度,因为不需要中断调用,在编译的时候内联函数可以直接呗镶嵌到目标代码中。  内联函数要做参数类型检查,这是内联函数相比的优势。  inline是指嵌入代码,就是...
  • 如果想把一个函数定义内联函数,则需要在函数名前面放置关键字inline,在调用函数之前需要对函数进行定义。 如果已定义的函数多于一行,编译器会忽略 inline 限定符。它能修饰任意函数,此关键字是一个建议,告诉...
  • 宏定义函数与内联函数
  • 宏定义和内联函数区别

    千次阅读 2018-01-31 14:59:42
    宏定义和内联函数区别  内联函数是代码被插入到调用者代码处的函数。如同 #define 宏,内联函数通过避免被调用的开销来提高执行效率,尤其是它能够通过调用(“过程化集成”)被编译器优化。 宏定义不检查函数参数...
  • C++内联函数宏定义的区别

    千次阅读 2018-12-30 10:58:56
    宏定义  宏定义作为C语言里面经常使用的工具,其实就相当于一个标签,在编译预处理时会直接将全部代码中的宏定义进行替换。  在很多方面十分的方便,比如 “ #define MAX(x,y) x &gt; y ? x : y ” 取最大...
  • 内联函数宏和普通函数的区别

    千次阅读 2018-08-07 21:48:12
    1、内联函数和宏的区别 宏定义不是函数,但是使用起来像函数。预处理器用复制宏代码的方式代替函数的调用,省去了函数压栈退栈过程,提高了效率。 内联函数本质上是一个函数,内联函数一般用于函数体的代码比较...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 22,645
精华内容 9,058
关键字:

内联函数和宏定义