【编程珠玑】内联函数和宏
一,内联函数的用法
内联函数从源码层层看,有函数的结构,而在编译后,却不具备函数的性质。编译时,类似宏替换,使用函数体替换调用处的函数名。一般在代码中用inline修饰,但是能否形成内联函数,需要看编译器对该函数定义的具体处理。
inline Tablefunction(int I) //是没有效果的,编译器只是把函数作为普通的函数申明,我们必须定义函数体。
Inline tablefunction(int I) {return I*I}; //这样我们才算定义了一个内联函数。我们可以把它作为一般的函数一样调用。但是执行速度确比一般函数的执行速度要快。
内联函数必须是和函数体申明在一起,才有效。
【注意】我们也可以将定义在类的外部的函数定义为内联函数,比如:
[html]
Class TableClass
{
private:
int i,j;
public:
int add() { return i+j;};
inline int dec() { return i-j;}
int GetNum();
}
inline int tableclass::GetNum()
{
return i;
}
上面申明的三个函数都是内联函数。在C++中,在类的内部定义了函数体的函数,被默认为是内联函数。而不管你是否有inline关键字。
二,内联函数的应用(可以访问对象的私有成员)
内联函数在C++类中,应用最广的,应该是用来定义存取函数。我们定义的 类中一般会把数据成员定义成私有的或者保护的,这样,外界就不能直接读写我们类成员的数据了。对于私有或者保护成员的读写就必须使用成员接口函数来进行。如果我们把这些读写成员函数定义成内联函数的话,将会获得比较好的效率。
[html]
Class sample
{
private:
int nTest;
public:
int readtest(){ return nTest;}
void settest(int i) {nTest=i;}
}
当然,内联函数也有一定的局限性。就是函数中的执行代码不能太多了,如果,内联函数的函数体过大,一般的编译器会放弃内联方式,而采用普通的方式调用函数。这样,内联函数就和普通函数执行效率一样了。
三,内联函数注意事项
1,在内联函数内不允许用循环语句和开关语句。否则编译将该函数视同普通函数
2,递归函数(自己调用自己的函数)是不能被用来做内联函数的。
3,内联函数只适合于只有1~5行的小函数。对一个含有许多语句的大函数,函数调用和返回的开销相对来说微不足道,所以也没有必要用内联函数实现。
4,内联函数的定义必须出现在内联函数第一次被调用之前。
5,类结构中所有在类说明内部定义的函数是内联函数。
四,宏的定义
带参数的宏定义和不带参数的宏定义。具体是指用一个指定的标志符来进行简单的字符串替换或者进行阐述替换。
宏展开:在c程序编译时将宏名替换成字符串的过程
#define max(a,b) ( (a)>(b) ) ? (a):(b)
五,宏的局限性
1,宏不能访问对象的私有成员。
2,宏的定义很容易产生二意性。
二义性例子:
#define TABLE_MULTI(x) (x*x)
TABLE_MULTI(10) //返回100,是正确的。
TABLE_MULTI(10+10) //我们期望的结果是400,而宏的调用结果是(10+10*10+10),结果是120
这显然不是我们要得到的结果。避免这些错误的方法,一是给宏的参数都加上括号。
#define TABLE_MULTI(x) ((x)*(x))
这样可以确保不会出错,但是,即使使用了这种定义,这个宏依然有可能出错
TABLE_MULTI(a++) //我们本意是希望得到(a+1)*(a+1)的结果,而宏的展开结果: (a++)*(a++)
如果a的值是4,我们得到的结果是4*4 = 16,a = 6。我们期望得到的是 5*5 = 25
六,内联函数和宏的区别
宏是由预处理器对宏进行替代,内联函数是编译器控制来实现的。
内联函数是真正的函数,只是在需要用到的时候,内联函数像宏一样的展开,所以取消了函数的参数压栈,减少了调用的开销。
你可以象调用函数一样来调用内联函数,而不必担心会产生于处理宏的一些问题。
摘自 小田的专栏
补充:软件开发 , 其他 ,