重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
引入内联函数的目的是为了解决程序中函数调用的效率问题。
创新互联公司专注于上党企业网站建设,响应式网站建设,购物商城网站建设。上党网站建设公司,为上党等地区提供建站服务。全流程按需网站开发,专业设计,全程项目跟踪,创新互联公司专业和态度为您提供的服务
函数是一种更高级的抽象。它的引入使得编程者只关心函数的功能和使用方法,而不必关心函数功能的具体实现;函数的引入可以减少程序的目标代码,实现程序代码和数据的共享。但是,函数调用也会带来降低效率的问题,因为调用函数实际上将程序执行顺序转移到函数所存放在内存中某个地址,将函数的程序内容执行完后,再返回到转去执行该函数前的地方。这种转移操作要求在转去前要保护现场并记忆执行的地址,转回后先要恢复现场,并按原来保存地址继续执行。因此,函数调用要有一定的时间和空间方面的开销,于是将影响其效率。特别是对于一些函数体代码不是很大,但又频繁地被调用的函数来讲,解决其效率问题更为重要。引入内联函数实际上就是为了解决这一问题。
在程序编译时,编译器将程序中出现的内联函数的调用表达式用内联函数的函数体来进行替换。显然,这种做法不会产生转去转回的问题,但是由于在编译时将函数休中的代码被替代到程序中,因此会增加目标程序代码量,进而增加空间开销,而在时间代销上不象函数调用时那么大,可见它是以目标代码的增加为代价来换取时间的节省。
inline的函数是复制到调用位置,而不是跳转调用,这样的好处是避免函数调用本身出栈入栈消耗额外的时间,而且高速缓存会更容易命中(一项CPU的技术,命中时会提高运行速度,数据不走内存避免了额外时间消耗)。。。 inline只用于内容重复,但代码很短的函数,避免出栈入栈消耗额外的时间,其实内联函数并不是真正意义的函数。。。而是对重复代码的简化。。。。
对于复杂函数,不建议用inline,因为他在每个调用位置都会复制编译,会让代码变得非常长,被100个位置调用,该函数的内存增加100倍,而且现在电脑非常快,inline其实根本没必要,一般只有几行的函数才有理由用inline,因为他的出栈入栈跳转相对本身代码运行时间的比例较高,而长代码就微乎其微。。。。其实inline知道有就行,现在编程很少用。。。
用的话这个函数代码也不要超过10行,而且通常C语言会用 宏代码来代替inline完成重复的短代码,宏其实效果比inline更好,这样inline使用频率更低, inline用的并不多。。。
为了运行效率。内联函数与普通函数相比,没有参数入栈出栈的过程,所以内联函数相当于是把函数体内的代码直接复制到调用的地方,因为少了参数传递过程,因此提高了效率。c++为了运行效率引入内联函数。
在c++中内联函数是对宏定义一种改造,因为利用内联函数取代宏定义得好处是:
1、可进行类型安全检查或自动类型转换、
例如:在c语言中,常用预处理器语句#define来代替一个函数定义。例如:
#define MAX(a,b) ((a)(b)? (a):(b))
该语句是在程序中每个出现Max(a,b)函数调用得地方,都被后面得表达式((a)(b)?(a):(b))所替代
不难发现其实对参数a,b来说都没有数据类型得定义,缺少一些安全性检查。
2、提高程序的运行效率
对于c++中一般得函数,被程序调用得时都需要为该函数开辟空间进行函数得压栈、出栈等所带来得开销,而
内联函数像宏一样被展开,调用内联函数的时候,由编译器负责把内联函数的函数体代码块替换到内联函数被调用的
地方,这一点与宏替换很相似;取消了函数参数压栈、出栈所带来的开销,从而减少了函数调用开销,提高程序得运
行效率。
所以,内联函数在项目开发中经常用到,所以关于内联函数得使用应用如下:
第一种 、内联函数得声明和函数体得定义在一起
例如:
inline int Max(int a, int b){return ((a b) ? a : b)};
第二种、c++类得成员函数也可以被定义为内联函数
class Student{
private:
int nID;
int nAge;
float fScore;
public:
void setID(int nid){ nID = nid; } //该成员函数默认自动为内联函数(隐式定义内联函数)
int getID(void){ return nID; } //该成员函数默认自动为内联函数(隐式定义内联函数)
inline void setAge(int nage) { nAge = nage; } //显式定义内联函数
inline int getAge(void) { return nAge; } //显式定义内联函数
void setScore(float fscore); //类定义体内没有声明为内联函数;
float getScore(void); //类定义体内没有声明为内联函数;
}
inline void Student::setScore(float fscore){ fScore = fscore; } //类定义体外实现为内联函数;
inline float Student::getScore(void) { return fScore; } //类定义体外实现为内联函数;
注意:(1)C++中,在类定义体内部定义了函数体的成员函数,被编译器默认为内联函数,而不管这个函数头前面是
否有关键字inline,比如:setID()、getID()、setAge()、getAge();
(2)以把实现在类定义体外部的成员函数定义为内联函数,这个时候在类定义体中只有成员函数头的声明,而
其实现是在类定义体外部,比如:setScore()和getScore();
内联函数的局限性:
1、由于内联函数与宏一样也是实现为代码替换,所以定义为内联函数的函数体不宜过大,如果函数体过
大,则某些普通的编译器就会放弃内联方式,而改用调用普通函数的方式,这样就失去了内联函数的意义了;所以,
内联函数的函数体代码不宜过大,一般就是3---4行代码即可;
2、由于内联函数是编译器在便宜阶段进行函数体展开的,所以,这就把类的内联函数的定义与实现都必须在
声明类的那个头文件中,而不能放在实现类的那个cpp文件中;这一点与模板template的特性相似
应该是c++中才有的,
inline 关键字用来定义一个类的内联函数,引入它的主要原因是用它替代C中表达式形式的宏定义。
表达式形式的宏定义一例:
#define ExpressionName(Var1,Var2) (Var1+Var2)*(Var1-Var2)
为什么要取代这种形式呢,且听我道来:
1.
首先谈一下在C中使用这种形式宏定义的原因,C语言是一个效率很高的语言,这种宏定义在形式及使用上像一个函数,但它使用预处理器实现,没有了参数压栈,代码生成等一系列的操作,因此,效率很高,这是它在C中被使用的一个主要原因。
2.
这种宏定义在形式上类似于一个函数,但在使用它时,仅仅只是做预处理器符号表中的简单替换,因此它不能进行参数有效性的检测,也就不能享受C++编译器严格类型检查的好处,另外它的返回值也不能被强制转换为可转换的合适的类型,这样,它的使用就存在着一系列的隐患和局限性。
3.
在C++中引入了类及类的访问控制,这样,如果一个操作或者说一个表达式涉及到类的保护成员或私有成员,你就不可能使用这种宏定义来实现(因为无法将this指针放在合适的位置)。
4. inline 推出的目的,也正是为了取代这种表达式形式的宏定义,它消除了它的缺点,同时又很好地继承了它的优点。
为什么inline能很好地取代表达式形式的预定义呢?
对应于上面的1-3点,阐述如下:
1. inline 定义的类的内联函数,函数的代码被放入符号表中,在使用时直接进行替换,(像宏一样展开),没有了调用的开销,效率也很高。
2.
很明显,类的内联函数也是一个真正的函数,编译器在调用一个内联函数时,会首先检查它的参数的类型,保证调用正确。然后进行一系列的相关检查,就像对待任何一个真正的函数一样。这样就消除了它的隐患和局限性。
3. inline 可以作为某个类的成员函数,当然就可以在其中使用所在类的保护成员及私有成员。
在何时使用inline函数:
首先,你可以使用inline函数完全取代表达式形式的宏定义。
另外要注意,内联函数一般只会用在函数内容非常简单的时候,这是因为,内联函数的代码会在任何调用它的地方展开,如果函数太复杂,代码膨胀带来的恶果很可能会大于效率的提高带来的益处。
速度是有代价的,inline和宏都是用空间换时间。
使用内联函数的时候要注意:
1.递归函数不能定义为内联函数
2.内联函数一般适合于不存在while和switch等复杂的结构且只有1~5条语句的小函数上,否则编译系统将该函数视为普通函数。
3.内联函数只能先定义后使用,否则编译系统也会把它认为是普通函数。
4.对内联函数不能进行异常的接口声明。