您的位置:首页 > 其它

宏定义和内联函数的区别

2013-10-01 15:42 253 查看
在程序员面试宝典第三版的6.4中,有个问题,内联函数和宏的差别是什么?






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

  1、.宏不能访问对象的私有成员。

  2、.宏的定义很容易产生二意性。

既然宏有一些难以避免的问题,怎么解决呢? 有个神奇的东西要登场了,那就是---内联函数,我们可以使用内联函数来取代宏的定义。而且事实上我们可以用内联函数完全取代预处理宏。

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

我们可以用inline来定义内联函数,不过,任何在C++类内部的声明部分定义的函数都会被自动的认为是内联函数。

下面我们来介绍一下内联函数使用过程中需要注意的几点:

1) 内联函数必须是函数体声明在一起才有效。像这样的声明inline
int Sum(int a);是没有效果的,编译器只是把函数作为普通的函数声明,我们必须把函数体和声明一起:

inline int Sum(int a) {return a*a};

2) 在C++中,在类的内部定义了函数体的函数,被默认为是内联函数,而不管你是否有inline关键字

Class XXX{
 Private:
  int i,j;
 Public: 
  int Add() { return i+j;};
  inline int Sum() { return i+j;};
}

如上所示,类内部函数Add和Sum的效果一样,虽然Add前面没有inline关键字,但是由于是在类内部,被默认为是内联函数。

当然,内联函数也有一定的局限性。就是函数中的执行代码不能太多了,如果,内联函数的函数体过大,一般的编译器会放弃内联方式,而采用普通的方式调用函数。这样,内联函数就和普通函数执行效率一样了。

内联函数与带参数宏定义的另一个区别是,内联函数的参数类型和返回值类型在声明中都有明确的指定;而带参数宏定义的参数没有类型的概念,只有在宏展开以后,才由编译器检查语法,这就存在很多的安全隐患。

程序员面试宝典中也有讲到,inline函数只用于某些情况,鉴于此,使用内联函数时,应注意以下问题:

1)内联函数的定义性声明应该出现在对该函数的第一次调用之前。

2)内联函数首先是函数,函数的很多性质都适用于内联函数,如内联函数可以重载。

3)在内联函数中不允许使用循环语句和switch结果,带有异常接口声明的函数也不能声明为内联函数。

& 另附上const与宏常量的区别:

1. const常量有数据类型,而宏常量没有数据类型

编译器可以对前者进行类型安全检查,而对后者只能进行字符替换,没有安全检查,并且在字符替换时可能会产生意料不到的错误。

2. 编译器对二者的调试

有些集成化的调试工具可以对const常量进行调试, 在 c++程序中只使用const常量而不使用宏常量,即const常量完全取代宏常量。

预处理器(preprocessor)

预处理器是在真正的翻译开始之前由编译器调用的独立程序。预处理器可以删除注释、包含其他文件以及执行宏(宏macro是一段重复文字的简短描写)替代。预处理器可由语言(如C)要求或以后作为提供额外功能(诸如为FORTRAN提供Ratfor预处理器)的附加软件。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: