轉載自:https://www.cnblogs.com/KellyHuang/p/4001470.html
在大多數機器上,函數調用does a lot of work:在調用函數前保存寄存器,調用結束后利用寄存器恢復現場;需要復制函數參數;程序跳轉到新的位置執行...
內斂函數(inline function)則沒有這個問題,簡單的我們可以這樣理解:Inline即“In line”
為什么說“In line”呢,先看內斂函數的聲明:
// inline version: find the shorter of two strings
inline const string &
shorterString(const string &s1, const string &s2)
{
return s1.size() <= s2.size() ? s1 : s2;
}
//那么當我們執行:
cout << shorterString(s1, s2) << endl;
//其實編譯時會變成:
cout << (s1.size() < s2.size() ? s1 : s2) << endl;
內斂函數感覺類似宏替換,但是inline在替換前有類型檢查,避免了宏的錯誤
聲明Inline函數時,編譯器會對函數有一個判斷:該函數作為內斂函數是否合理?如果不合理,就算我們聲明了Inline編譯器也會將函數作為普通函數處理。
在類體中定義的成員函數的規模一般都很小,而系統調用函數的過程所花費的時間開銷相對是比較大的。調用一個函數的時間開銷遠遠大於小規模函數體中全部語句的執行時間。為了減少時間開銷,如果在類體中定義的成員函數中不包括循環等控制結構,C++系統會自動將它們作為內置(inline)函數來處理。
也就是說,在程序調用這些成員函數時,並不是真正地執行函數的調用過程(如保留返回地址等處理),而是把函數代碼嵌入程序的調用點。這樣可以大大減少調用成員函數的時間開銷。C++要求對一般的內置函數要用關鍵字inline聲明,但對類內定義的成員函數,可以省略inline,因為這些成員函數已被隱含地指定為內置函數。如:
class Student
{
public :
void display( )
{
cout<<"num:"<<num<<endl;cout<<"name:"
<<name<<endl;cout<<"sex:"<<sex<<endl;
}
private :
int num;
string name;
char sex;
};
其中第3行
void display( )
也可以寫成
inline void display( )
將display函數顯式地聲明為內置函數。
以上兩種寫法是等效的。對在類體內定義的函數,一般都省寫inline。
應該注意的是,如果成員函數不在類體內定義,而在類體外定義,系統並不把它默認為內置(inline )函數,調用這些成員函數的過程和調用一般函數的過程是相同的。如果想將這些成員函數指定為內置函數,應當用inline作顯式聲明。如:
class Student
{
public : inline void display( );//聲明此成員函數為內置函數
private :
int num;
string name;
char sex;
};
inline void Student::display( ) // 在類外定義display函數為內置函數
{
cout<<"num:"<<num<<endl;cout<<"name:"<<name<<endl;cout<<"sex:"<<sex<<endl;
}
值得注意的是,如果在類體外定義inline函數,則必須將類定義和成員函數的定義都放在同一個頭文件中(或者寫在同一個源文件中),否則編譯時無法進行置換(將函數代碼的拷貝嵌入到函數調用點)。但是這樣做,不利於類的接口與類的實現分離,不利於信息隱蔽。雖然程序的執行效率提高了,但從軟件工程質量的角度來看,這樣做並不是好的辦法。只有在類外定義的成員函數規模很小而調用頻率較高時,才將此成員函數指定為內置函數。
