内联函数以及它和宏的区别

内联函数以及它和宏的区别

一、 概念

inline 修饰的函数叫做内联函数。
内联函数在调用时不是像一般函数那样要转去执行被调用函数的函数体,执行完成后在转回调用函数中,执行其后的语句;而是在调用处用内联函数体的代码来替换,这样没有函数压栈,将会节省调用的开销,提高运行效率。

//内联函数
inline int Max(int a, int b)
{
    if (a < b)
        return b;
    return a;
}
int main()
{
    int i=1;
    int j=2;
    int max = Max(i, j);
    cout << "max=" << max << endl;
    return 0;
}

二、 特性

  • 用 inline 来定义内联函数,但任何在类的说明部分定义的函数都会被自动的认为是内联函数。
  • 内联函数必须是和函数体声明在一起才有效。
inline Function(int i); 
// 没有效果,编译器只是把函数作为普通的函数声明。所以必须定义函数体
inline Function(int i){ return i*i }
// 这样才算是定义了一个内联函数。
  • 可以将定义在类外的函数定义为内联函数:
//类的内联函数
class Math
{
public:
    int add()
    {
        return i + j;
    }
    inline int sub()
    {
        return i - j;
    }
    int GetNum();

private:
    int i, j;
};
inline int Math::GetNum()
{
    return i;
}
// 该类中声明了3个内联函数,在C++中,在类的内部定义了函数体的函数,被默认为是内联函数。而不管你是否有关键字inline
  • 作为成员接口函数对类中的私有成员和保护成员进行读写
//作为成员接口函数对类中的私有成员和保护成员进行读写。
class RW
{
public:
    int Readi()
    {
        return _i;
    }
    void Seti(int i)
    {
        _i = i;
    }
private:
    int _i;
};
  • inline是一种以空间换时间的做法,省去调用函数的开销。使用内联函数可以节省运行时间,但却增加了目标程序的长度。所以代码很长或者有循环、递归的函数不适宜使用内联函数,就算用了编译器也会放弃内联方式,而采用像调用普通函数的方式去调用它。只有那些那些规模较小而又被频繁调用的简单函数,才适合定义为inline函数。

三、面试题

  1. 为什么要使用宏,宏有什么优点?
    答:因为函数的调用必须要将程序执行的顺序转移到函数所存放在内存中的某个地址,将函数的内容执行完后再返回到转去执行该函数前的地方。这种转移操作要求在转去执行前要保存现场并记忆执行的地址,转回后要恢复现场,并按原来保存地址继续执行。因此函数调用要有一定的时间和空间方面的开销,于是将影响其效率。而宏只是在预处理的地方将代码展开,不需要额外的空间和时间方面的开销,所以调用一个宏比调用一个函数更有效率。

  2. 宏有什么缺点?
    a.宏不能访问对象的私有成员
    b.宏的定义很容易产生二义性
    #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++)*(a++),如果a=4,结果为4*4=16,a=6,而我们期望的是4*4=16,a=5.

  3. 宏函数和内联函数的区别?
    内联函数和宏的区别在于:宏是由预处理器对宏进行替换的,而内联函数是通过编译器控制实现的。而且内联函数是真正的函数,只是在需要用到的时候内联函数像宏一样的展开,所以取消了函数的参数压栈,减少了调用的开销。所以可以像调用函数一样来调用内联函数,而不必担心会产生像宏出现的问题。

四、注意
1. 在C++中强制建议使用const来代替宏常量,使用内联函数来代替宏函数
2. const和内联函数在进行编译时不仅进行替换,而且还会进行参数类型检测,提高了程序的安全性。
3. 内联函数可以是普通函数,也可以是类的成员函数;函数式宏不能作为类的成员函数。

猜你喜欢

转载自blog.csdn.net/bit666888/article/details/81182975