以下内容 转自百度百科:
一、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函数:

简单提一下inline 的使用吧:
1.在类中定义这种函数:
class ClassName{
.....
....
INT GetWidth(){return m_lPicWidth;}; // 如果在类中直接定义,不需要用inline修饰,编译器自动化为内联函数
.... //此说法在《C++ Primer》中提及
....
}
2.在类外定义前加inline关键字:
class Account {
public:
Account(double initial_balance) { balance = initial_balance; } //与1相同
double GetBalance(); //在类中声明
double Deposit( double Amount );
double Withdraw( double Amount );
private:
double balance;
};
inline double Account::GetBalance() { return balance; } //在类外定义时添加inline关键字
inline double Account::Deposit( double Amount ) { return ( balance += Amount ); }
inline double Account::Withdraw( double Amount ) { return ( balance -= Amount ); }
 
此外还有一些规则需注意:
1、inline说明对编译器来说只是一种建议,编译器可以选择忽略这个建议。比如,你将一个长达1000多行的函数指定为inline,编译器就会忽略这个inline,将这个函数还原成普通函数。
2、在调用内联函数时,要保证内联函数的定义让编译器"看"到,也就是说内联函数的定义要在头文件中,这与通常的函数定义不一样。但如果你习惯将函数定义放在CPP文件中,或者想让头文件更简洁一点,可这样做:
//SomeInline.h中
#ifndef SOMEINLINE_H
#define SOMEINLINE_H
inline Type Example(void);
//........其他函数的声明
#include“SomeInlie.cpp” //源文件后缀名随编译器而定
#endif
//SomeInline.cpp中
#include"SomeInline.h"
Type Example(void)
{
//..........
}
//...............其他函数的定义
以上方法是通用、有效的,可放心使用,不必担心在头文件包含CPP文件会导致编译错误。
 
 
以下内容,转自百度文库,补充说明内联的 使用目的和作用:
内联函数是一种编译机制,优点从代码上是看不出来的,但是程序的执行效率上有差别,通常,编译器对函数调用的处理是一种类似中断的方式,即当执行到函数调用语句时,程序把当前所有的状态信息比如CPU所有寄存器(其中一个很重要的就是指令指针寄存器)的值保存起来,然后放心大胆地转去执行那个函数的代码,执行完后再返回原来的地方,恢复原先保存过的状态信息,于是也就可以接着原来被中断的指令继续往下执行。这样,就很容易实现代码的结构化,因为可以把一些独立的功能模块写成函数,函数内部的变量和外部的变量互不影响,而且函数执行完后就可以释放这个函数内部变量的所使用的内存空间(这就是为什么函数退出后,其内部变量不再有效),对内存的使用也是很经济的(否则,如果一个大的程序全部由一个函数组成,那么所有的变量都得自始至终地占用内存空间),当然,还有其他优点,比如可以实现递归,总之是好处多多。  可是,任何事情往往都有两方面,这样做虽然好处多多,但也是有代价的,那就是前面所说的,任何一次函数调用,程序都得进行保存和恢复状态信息的动作,用数据结构的术语说就是进栈和退栈,当然,还有内存分配的过程,如果函数的代码非常少,这种代价并不是可忽略的,比如说,你编写一个类,里面有个记录状态的成员变量:  Class MyClass  {  private:  int m_iState;  }  按照面向对象的思想,函数的属性应尽量的私有化,但外部怎么获得这个属性值呢?一般的方法就是加一个共有函数,这就实现的面向对象思想中所谓“通过公用接口操作对象的私有属性”。于是就变成了:  Class MyClass  {  public:  int GetState();  private:  int m_iState;  }   int MyClass::GetState()  {  return m_iState;  }  这样一来,面向对象思想倒是体现出来了,但你的CPU会恨你:“你丫一个鸟函数就返回一个整数却让老子进一次栈、弹一次栈”,内存也会埋怨:“兄弟也得跟着分配内存!”  但对你来说,也很委屈,怎么办,把所有的属性都改成public?让外部内码直接访问?况且,那样也不解决所有问题,因为有时候即使不是为了面向对象,我们也需要把独立的功能模块做成函数,比如说产生随机数的函数。我想  int iRand=rand();  总比:int iRand=((int)(MULTIPLIER * Seed + INCREMENT)>>16)&0x7fff;  看起来舒服吧?(我这里只是打个比方,VC的rand函数并不是内联函数)  而内联函数就是解决这个问题了,对于程序员,他还是把独立功能写成函数的形式,但只要声明为内联,编译器就不把它编译成一次函数调用,而只是类似于把函数的代码拷贝到被调用的地方,而且这完全是编译器私下里完成的,原来的访问权限等问题丝毫不受影响。这不是两全齐美了吗:在保证代码的面向对象性和结构化不受损失的条件下,程序的效率也没有损失,比如上面那个类,就变成了:  Class MyClass  {  public:  inline int GetState();  private:  int m_iState;  }   int inline MyClass::GetState()  {  return m_iState;  }  有一点要注意,内联函数要跟类的声明写在同一个文件中,否则编译会出错。按照VC管理源文件的风格来说,就是内联函数最好写在声明类的.h文件中,而不是像一般函数那样写在实现类的.cpp文件中。  当然,内联函数还有另外一种写法,就是直接写在类中,此时,不必使用“inline”关键字。  Class MyClass  {  public:  int GetState(){ return m_iState; }  private:  int m_iState;  }  最后,还要注意,内联函数只是一种编译机制,用上面两种形式声明的函数仅仅是建议编译器进行内联,而编译器是否内联不一定。正如前面所说,函数调用的开销只是对小的函数不可忽略,对于重量级的函数还是可以忽略的,而且在绝大多数的场合,函数调用才是人间正道,才是解决问题的最佳。所以大多数编译器并不把带有循环、递归等或者代码比较多的函数进行内联编译,有的甚至不允许声明成内联的。    
 
posted on 2013-03-27 14:25  微微来了  阅读(910)  评论(0编辑  收藏  举报