欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【C++】宏函数与内联函数的区别

程序员文章站 2024-03-21 10:04:34
...

知识点:宏函数与内联函数

一、概念


  以inline修饰的函数就叫做内联函数,C++编译器在编译时会在调用内联函数时地方展开,没有函数压栈的开销,内联函数提升程序的运行效率。

  内联函数在调用时不是像一般函数那样要转去执行被调用函数的函数体,执行完成后在转回调用函数中,执行其后的语句;而是在调用处 用内联函数体 的代码来替换,以这样的方式结婚时呢个调用开销,提高运行效率。

#include<iostream>
using namespace std;
//内联函数
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;
}

二、特性


  1. inline是一种以空间换时间的做法,省去调用函数的开销。使用内联函数可以节省运行时间,但却增加了目标程序的长度。所以代码很长或者有循环、递归的函数不适宜使用内联函数,就算用了编译器也会放弃内联方式,而采用像调用普通函数的方式去调用它。只有那些那些规模较小而又被频繁调用的简单函数,才适合定义为inline函数。

  2. 内联函数必须是和函数体声明在一起才有效。不建议将声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到。

inline ADD(int left,int right); 
// 没有效果,编译器只是把函数作为普通的函数声明。所以必须定义函数体
inline ADD(int left,int right){ return left+right;}
// 这样才算是定义了一个内联函数。

  3. 可以将定义在类外的函数定义为内联函数

//类的内联函数
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个内联函数add、sub和GetNum,在C++中,在类的内部定义了函数体的函数,被默认为是内联函数。而不管你是否有关键字inline

  4. 作为成员接口函数对类中的私有成员和保护成员进行读写

//作为成员接口函数对类中的私有成员和保护成员进行读写。
class RW
{
public:
    int Readi()
    {
        return _i;
    }
    void Seti(int i)
    {
        _i = i;
    }
private:
    int _i;
};

三、优缺点

内联函数的优缺点?

优点:

  1. 因为内联函数是函数,函数参数有类型,因此在编译阶段会进行参数类型检测,安全性更高
  2. 在Debug模式下默认不会展开,可以进行调试,也可以通过对编译器设置来验证到底是否展开
  3. 内联函数不用像宏函数那样到处加括号,实现起来更简单
  4. 不会有副作用
  5. 内联函数在编译阶段已经展开,少了函数的调用,提高函数的运行效率

缺点:

  1. 每个使用内联函数的位置几乎都会被展开,会造成代码膨胀。

宏的优缺点?

(1)宏常量的优缺点

  优点:一改全改,降低出错概率,提高代码的可读性

  缺点:在预处理节点进行替换,不会进行类型检测,代码安全性低

  因此在C++中建议尽量使用const修饰的常量替换宏常量。

(2)宏函数的优缺点

  优点:

  • 不是函数,少了函数调用的开销,提高程序的运行效率
  • 可少些一些代码,因为宏函数可以封装多条语句
  • 可提高代码的可读性

  缺点:

  • 宏函数预处理阶段被替换,不会进行类型的检测,代码安全性低
  • 宏函数不能进行调试
  • 容易出错,宏函数的每一部分都需要加上括号
  • 每个宏函数的位置都会被展开,会造成代码的膨胀
  • 宏函数可能会有副作用

四、笔试题

第一题:为什么要是用宏,宏有什么优缺点?

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

​   优点:
​     1.增强代码的复用性。
​      2.提高性能与可读性。
​   缺点:
​      1.不方便调试宏。(因为预编译阶段进行了替换)
​      2.导致代码可读性差,可维护性差,容易产生二义性。
​      3.没有进行类型的检测 ,安全性低。

第二题:宏函数与内联函数的区别?

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

第三题:C++有哪些技术替代宏?

​    1.常量定义 换用 const修饰的常量

​    2.函数定义 换用 内联函数

注意C++中被const修饰的变量已经是常量,具有宏替换属性

const int a=10;
int arry[a]={0};

  在C++中能够编译通过,a被const修饰,a为常量表达式

  在C编译器中就编译报错,这是因为在C语言中,被const修饰的变量不能称其为常量,仍旧是变量,只不过该变量不能够被修改。即在C语言中,被const修饰的变量是一个不能修改的变量,不能被称为常量。

五、总结

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

相关标签: C/C++ c++ 面试