大厂面试重要C++知识(二)—— 内联函数和宏的区别与联系

目录

  • 一、内联函数
    • 内联函数定义
    • 代码实现
    • 优缺点
    • 关键
  • 二、内联函数和宏(macro)的区别
    • 内联函数和宏的区别
  • 参考文章

内联函数和宏做为C和C++的基础,具有提高执行效率的功能。那么既然存在了宏,为什么还要内联函数?他们有什么区别和联系呢?以下展开。

一、内联函数

内联函数定义

  • 内联函数是C++为降低小型程序调用开销而采取的一种机制。
  • 函数在调用时,需要在栈中为形参和局部变量开辟空间,将实参的值赋值给形参;还有函数执行前的现场状态和返回地址都要压入栈中,以便函数返回后继续执行,这个过程带来时间和空间的开销。同理,在退出函数时也要时间的开销。
  • 因此,使用内联函数机制定义一些简单、代码短、常用到的函数。
  • 内联函数和普通函数的区别:编译器处理内联函数语句时,不会将语句编译成函数调用的指令,而是直接将整个函数体的代码嵌入调用语句处,就像整个函数体在调用处重写了一遍。
  • 个人理解,有点像编写代码时不写函数而直接书写相应的代码,只不过写内联函数是编译器替你做了这些事情(写重复的代码),而自己只需要封装好函数加上内联标志,编译器帮你完成重复代码的书写并翻译。

代码实现

在代码实现很简单,在定义函数时,在返回值类型上写inline关键字即可。

inline int Max(int a, int b)
{
    return a > b ? a : b; 
}

优缺点

优点:即可以方便我们像调用函数一样解决重复代码的问题,又不用付出函数调用时压栈、出栈的时间开销。

缺点:使用内联函数,以空间换时间,增加了编译后的代码体积。如果函数里代码量大、出现了循环、递归等,执行函数的花销远大于调用函数的开销,那么就没有必要使用内联函数,甚至使得可执行程序变得很大,浪费大量的空间。

关键

  • 调用内联函数的语句前必须已经出现内联函数的定义(即完整的函数代码),而不能只出现内联函数的声明。

  • 在函数前头加上inline声明为内联函数,但是编译器会根据函数的大小、是否有循环等判断是否满足内联条件,不满足则不是内联函数。

  • 内联一般在中使用,如get()、set()方法。

  • 内联的定义最好放在头文件,即整个函数体放在头文件里。这其实是个工程的问题,因为C++工程中的类的定义一般写在头文件中,具体实现代码在源文件中。一般来说,头文件中不允许出现函数的定义,但是由于内联函数必须在调用它的每个文本文件中被定义,所以没有在类体中定义的内联成员函数必须被放在类定义出现的头文件中。

    //这是test.h
    #pragma once
    class test
    {
    public:
    	int getValue();
    private:
    	int value;
    };
    inline int test::getValue()
    {
    	return value;
    }
    
    

二、内联函数和宏(macro)的区别

首先看看宏的定义:

  宏,也就是宏定义,是C语言三种预处理功能之一。例如:#define N 100,在预处理工作过程中,代码中出现的所有N(宏名),都会被100(替换文本)替代,并且是原地展开

  宏函数,也就是带参数的宏定义,和函数类似又不同。宏函数在预处理期间处理,而函数则在编译时处理;宏函数在上面提到是原地展开,直接将代码替换,并不需要像函数调用时的各种开销,速度更快。

不过宏函数有个缺点,宏是原地替换的,所以可能遇到运算符优先级的不同而带来错误。最好每个变量都加上括号。

比如下面这个错误案例:

#include 
using namespace std;

#define DOUBLE(x) 2 * x

int main()
{
    cout << DOUBLE(2) << endl;
    cout << DOUBLE(1 + 1) << endl;
}

  上面的代码,如果按照普通函数的思路,那么2 和 1 + 1其实是一致的,所以两者结果应该都是4,但是运行的结果却是4 和 3。原因是,宏在预处理时是原地替换,DOUBLE(1 + 1)在预处理时被替换为:2 * x + 1,自然结果就不是我们所想的。所以,宏函数中的参数都尽量带上括号,带上括号后在文本替换时就能够保证优先级顺序不出错。

  虽然上面的宏函数通过加括号后可以无误地完成需求,但是如果一个函数很复杂,每个变量都要加括号,写起来很费劲,代码看起来也很不舒服。所以,之前提到的内联函数就派上用场了。那么宏和内联函数有什么异同点呢?

内联函数和宏的区别

  • 宏是预处理时将代码原地替换(文本替换),而内联函数是在预处理的下一个步骤编译时将代码嵌入调用处。
  • 内联函数有类型检查、语法判断,而宏没有。
  • 宏和内联函数的展开还是有区别的,宏函数定义时每个参量都最好加上括号,而内联函数本质上还是函数并没有这么多的要求。
  • 内联函数通过inline关键字提醒编译器,编译器可以拒绝不符合条件的内联;而宏是在预处理时强制替换。
  • 宏不能直接访问类的私有成员,这种情况下使用内联函数会比较好,如get()、set()操作类的私有成员。
  • 因为宏在预处理时已经被原地替换了,所以宏函数不能够进入内部调试。
  • 两者相对于普通函数都有提高效率的作用,在不同场景使用根据需求使用宏或者内联,两者各有千秋。

参考文章

  • C++内联函数定义
  • C++内联详解

你可能感兴趣的:(C/C++,c++,编程语言,内联函数,面试)