inline与宏定义

2015/05/08 C和C++基础

inline(内联函数)是C++引入的机制,其目的是解决使用宏定义的一些缺点。

22.为什么要引入内联函数?

引入内联函数的主要目的是用它替代C中表达式形式的宏定义,解决程序中函数调用的效率问题。

#define ExpressionName(Var1,Var2)  (Var1+Var2)*(Var1-Var2)

这种宏定义在形式及使用上像一个函数,但它使用预处理器实现,没有了参数压栈、代码生成等一系列的操作,因此效率很高

这种宏定义在形式上类似于一个函数,但在使用它的时候,只是做预处理器符号表中的简单替换,因此它不能进行参数有效性检测(也就是不能享受C++编译器严格类型检查的好处)

同时它的返回值也不能被强制转换为可转换的合适类型,因此宏定义存在一系列的隐患和局限性。

在C++中引入了类及类的访问机制,如果一个操作或者说一个表达式涉及到类的保护或私有成员,你就不能使用这种宏定义来实现(因为无法将this指针放在合适的位置)。

inline内联函数推出的目的是为了取代这种表达形式的宏定义,消除宏定义的缺点,同时又很好地继承了它的优点。

23.为什么inline能很好地取代表达式形式的宏定义

inline定义类的内联函数,函数代码被放入符号表中,在使用时直接进行替换(像宏一样展开),没有了调用的开销,效率很高

类的内联函数也是一个真正的函数。编译器在调用一个内联函数时,首先会检查它的参数类型,保证调用正确,然后在进行一些列的相关检查,就像对待一个真正的函数一样,消除它的隐患性和局限性

inline可以作为某个类的成员函数,当然可以使用所在类的保护成员及私有成员。

24.说明内联函数使用的场合

首先使用inline函数完全可以取代表达式形式的宏定义。

内联函数在C++类中应用最广,是用来定义存取函数。定义的类中一般会把数据成员定义成私有的或者保护的,这样,外界就不能直接读写类成员的数据了。对于私有或者保护成员的读写就必须使用成员接口函数来进行。如果把这些读写成员函数定义成内联函数的话,将会获得比较好的效率。例如:

class A{
private:
	int nTest;
public:
	int readTest(){
		return nTest;
	}
	void setTest(int i);
};

inline void A::setTest(int i){
	nTest=i;
}
25.为什么不把所有的函数定义成内联函数

内联是以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率。一方面,如果执行函数体内代码的时间相比于函数调用的开销较大,那么效率的收获会很少,因为内联函数本身就是为了消除调用的时间开销,也就是调用越频繁,调用时间就越长,消除调用时间越明显,如果执行函数体内代码的时间相比于函数调用的开销较大,说明调用并不频繁。另一方面,每一处内联函数的调用都要复制代码,將使程序的总代码量增大,消耗更多的内存空间。

因此以下情况不宜使用内联函数:

1.如果函数体内的代码较长,使用内联将导致内存消耗代价较高。

2.如果函数体内出现循环,那么执行函数体内代码的时间要比函数调用的开销大。

另外,类的构造函数和析构函数容易让人误解成使用内联函数更有效,要当心构造函数和析构函数可能会隐藏一些行为,如“偷偷地”执行了基类或成员对象的构造函数和析构函数。所以不要随便地将构造函数和析构函数的定义体放在类声明中。

一个好的编译器将会根据函数的定义体,自动地取消不值得的内联。

内联函数与宏有什么区别?

1.内联函数在编译时展开,宏在预编译时展开;

2.在编译的时候内联函数可以直接被嵌入到目标代码中,而宏只是一个简单的文本替换。

3.内联函数可以完成诸如类型检测、语句是否正确等编译功能,宏就不具有这样的功能。

4.宏不是函数,inline函数是函数。

5.宏定义时要小心处理宏参数(一般情况是把参数用括号括起来),否则容易出现二义性,而内联函数定义时不会出现二义性。

Search

    Post Directory