亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

C++ 關鍵字 inline詳細介紹

2020-01-26 15:37:47
字體:
來源:轉載
供稿:網友

1.  內聯函數

在C++中我們通常定義以下函數來求兩個整數的最大值:

復制代碼 代碼如下:

int max(int a, int b)
{
 return a > b ? a : b;
}

為這么一個小的操作定義一個函數的好處有:

① 閱讀和理解函數 max 的調用,要比讀一條等價的條件表達式并解釋它的含義要容易得多

② 如果需要做任何修改,修改函數要比找出并修改每一處等價表達式容易得多

③ 使用函數可以確保統一的行為,每個測試都保證以相同的方式實現

④ 函數可以重用,不必為其他應用程序重寫代碼

雖然有這么多好處,但是寫成函數有一個潛在的缺點:調用函數比求解等價表達式要慢得多。在大多數的機器上,調用函數都要做很多工作:調用前要先保存寄存器,并在返回時恢復,復制實參,程序還必須轉向一個新位置執行

C++中支持內聯函數,其目的是為了提高函數的執行效率,用關鍵字 inline 放在函數定義(注意是定義而非聲明,下文繼續講到)的前面即可將函數指定為內聯函數,內聯函數通常就是將它在程序中的每個調用點上“內聯地”展開,假設我們將 max 定義為內聯函數:

復制代碼 代碼如下:

inline int max(int a, int b)
{
 return a > b ? a : b;
}

則調用: cout<<max(a, b)<<endl;


在編譯時展開為: cout<<(a > b ? a : b)<<endl;

從而消除了把 max寫成函數的額外執行開銷

2.  內聯函數和宏

無論是《Effective C++》中的 “Prefer consts,enums,and inlines to #defines” 條款,還是《高質量程序設計指南――C++/C語言》中的“用函數內聯取代宏”,宏在C++中基本是被廢了,在書《高質量程序設計指南――C++/C語言》中這樣解釋到:

3.  將內聯函數放入頭文件

關鍵字 inline 必須與函數定義體放在一起才能使函數成為內聯,僅將 inline 放在函數聲明前面不起任何作用。

如下風格的函數 Foo 不能成為內聯函數:

復制代碼 代碼如下:

inline void Foo(int x, int y);   // inline 僅與函數聲明放在一起  
void Foo(int x, int y)
{
 ...
}

而如下風格的函數 Foo 則成為內聯函數:

復制代碼 代碼如下:

void Foo(int x, int y);  
inline void Foo(int x, int y)   // inline 與函數定義體放在一起
{
 ...
}

所以說,C++ inline函數是一種“用于實現的關鍵字”,而不是一種“用于聲明的關鍵字”。一般地,用戶可以閱讀函數的聲明,但是看不到函數的定義。盡管在大多數教科書中內聯函數的聲明、定義體前面都加了 inline 關鍵字,但我認為 inline 不應該出現在函數的聲明中。這個細節雖然不會影響函數的功能,但是體現了高質量C++/C 程序設計風格的一個基本原則:聲明與定義不可混為一談,用戶沒有必要、也不應該知道函數是否需要內聯。

定義在類聲明之中的成員函數將自動地成為內聯函數,例如:

復制代碼 代碼如下:

class A

public:
 void Foo(int x, int y) { ... }   // 自動地成為內聯函數 
}

但是編譯器是否將它真正內聯則要看 Foo函數如何定義

內聯函數應該在頭文件中定義,這一點不同于其他函數。編譯器在調用點內聯展開函數的代碼時,必須能夠找到 inline 函數的定義才能將調用函數替換為函數代碼,而對于在頭文件中僅有函數聲明是不夠的。

當然內聯函數定義也可以放在源文件中,但此時只有定義的那個源文件可以用它,而且必須為每個源文件拷貝一份定義(即每個源文件里的定義必須是完全相同的),當然即使是放在頭文件中,也是對每個定義做一份拷貝,只不過是編譯器替你完成這種拷貝罷了。但相比于放在源文件中,放在頭文件中既能夠確保調用函數是定義是相同的,又能夠保證在調用點能夠找到函數定義從而完成內聯(替換)。

但是你會很奇怪,重復定義那么多次,不會產生鏈接錯誤?

我們來看一個例子:

A.h :

復制代碼 代碼如下:

class A
{
public:
 A(int a, int b) : a(a),b(b){}
 int max();

private:
 int a;
 int b;
};

A.cpp :

復制代碼 代碼如下:

#include "A.h"

inline int A::max()
{
 return a > b ? a : b;
}

Main.cpp :

復制代碼 代碼如下:

#include <iostream>
#include "A.h"
using namespace std;

inline int A::max()
{
 return a > b ? a : b;
}

int main()
{
 A a(3, 5);
 cout<<a.max()<<endl;
 return 0;
}

一切正常編譯,輸出結果:5

 


倘若你在Main.cpp中沒有定義max內聯函數,那么會出現鏈接錯誤:

error LNK2001: unresolved external symbol "public: int __thiscall A::max(void)" (?max@A@@QAEHXZ)main.obj
找不到函數的定義,所以內聯函數可以在程序中定義不止一次,只要 inline 函數的定義在某個源文件中只出現一次,而且在所有源文件中,其定義必須是完全相同的就可以。

在頭文件中加入或修改 inline 函數時,使用了該頭文件的所有源文件都必須重新編譯。

4.  慎用內聯

內聯雖有它的好處,但是也要慎用,以下摘自《高質量程序設計指南――C++/C語言》:

而在Google C++編碼規范中則規定得更加明確和詳細:

內聯函數:

Tip: 只有當函數只有 10 行甚至更少時才將其定義為內聯函數.

定義: 當函數被聲明為內聯函數之后, 編譯器會將其內聯展開, 而不是按通常的函數調用機制進行調用.
優點: 當函數體比較小的時候, 內聯該函數可以令目標代碼更加高效. 對于存取函數以及其它函數體比較短, 性能關鍵的函數, 鼓勵使用內聯.
缺點: 濫用內聯將導致程序變慢. 內聯可能使目標代碼量或增或減, 這取決于內聯函數的大小. 內聯非常短小的存取函數通常會減少代碼大小, 但內聯一個相當大的函數將戲劇性的增加代碼大小. 現代處理器由于更好的利用了指令緩存, 小巧的代碼往往執行更快。
結論: 一個較為合理的經驗準則是, 不要內聯超過 10 行的函數. 謹慎對待析構函數, 析構函數往往比其表面看起來要更長, 因為有隱含的成員和基類析構函數被調用!
另一個實用的經驗準則: 內聯那些包含循環或 switch 語句的函數常常是得不償失 (除非在大多數情況下, 這些循環或 switch 語句從不被執行).
有些函數即使聲明為內聯的也不一定會被編譯器內聯, 這點很重要; 比如虛函數和遞歸函數就不會被正常內聯. 通常, 遞歸函數不應該聲明成內聯函數.(遞歸調用堆棧的展開并不像循環那么簡單, 比如遞歸層數在編譯時可能是未知的, 大多數編譯器都不支持內聯遞歸函數). 虛函數內聯的主要原因則是想把它的函數體放在類定義內, 為了圖個方便, 抑或是當作文檔描述其行為, 比如精短的存取函數.

-inl.h文件:


Tip: 復雜的內聯函數的定義, 應放在后綴名為 -inl.h 的頭文件中.


內聯函數的定義必須放在頭文件中, 編譯器才能在調用點內聯展開定義. 然而, 實現代碼理論上應該放在 .cc 文件中, 我們不希望 .h 文件中有太多實現代碼, 除非在可讀性和性能上有明顯優勢.

如果內聯函數的定義比較短小, 邏輯比較簡單, 實現代碼放在 .h 文件里沒有任何問題. 比如, 存取函數的實現理所當然都應該放在類定義內. 出于編寫者和調用者的方便, 較復雜的內聯函數也可以放到 .h 文件中, 如果你覺得這樣會使頭文件顯得笨重, 也可以把它萃取到單獨的 -inl.h 中. 這樣把實現和類定義分離開來, 當需要時包含對應的 -inl.h 即可。

本文參考書目:《C++ Primer》、《高質量程序設計指南――C++/C語言》、Google C++編碼規范

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩成人在线电影网| 亚洲片av在线| 高清日韩电视剧大全免费播放在线观看| 欧美中文在线免费| 久久久久久网站| 亚洲成人av资源网| 国产成人精品在线视频| 播播国产欧美激情| 亚洲缚视频在线观看| www.亚洲天堂| 欧美精品激情blacked18| 久久国产精品久久精品| 久久久国产91| 日本91av在线播放| 九九热精品在线| www.日韩.com| 久久久成人精品视频| 欧洲精品毛片网站| 一道本无吗dⅴd在线播放一区| 日本精品久久电影| 久久福利网址导航| 日韩欧美中文第一页| 国产成人福利夜色影视| 中文字幕日韩视频| 69国产精品成人在线播放| 最新69国产成人精品视频免费| 久久久www成人免费精品| 亚洲裸体xxxx| 超碰97人人做人人爱少妇| 久久久女人电视剧免费播放下载| 欧美一级大胆视频| 欧美极品欧美精品欧美视频| 精品国产区一区二区三区在线观看| 国产精品国产亚洲伊人久久| 成人黄色影片在线| 日韩欧美成人免费视频| 欧美日韩在线第一页| 国产成人综合精品| 久久精品人人爽| 亚洲女人天堂成人av在线| 久久精品2019中文字幕| 97国产在线观看| 日韩视频中文字幕| 亚洲精品日韩在线| 国产精品高潮视频| 日韩成人av在线| 九九热99久久久国产盗摄| 久久久久久久久久久av| 庆余年2免费日韩剧观看大牛| 性欧美xxxx视频在线观看| 欧美精品在线免费观看| 亚洲欧美三级在线| 日韩av在线免费观看一区| www.日韩.com| 成人久久18免费网站图片| 成人福利在线观看| 成人激情视频小说免费下载| 久久久噜久噜久久综合| 久久久久久久久久久av| 欧美视频二区36p| 日韩美女视频免费在线观看| 亚洲国产另类 国产精品国产免费| 欧美激情一二三| 国内成人精品视频| 欧美亚洲视频在线观看| 亚洲香蕉成人av网站在线观看| 国产亚洲欧美视频| 欧美巨猛xxxx猛交黑人97人| 国产99视频精品免视看7| 国产精品午夜国产小视频| 久久久久国产精品免费| 亚洲日韩欧美视频一区| 日韩av在线网站| 国产精品自产拍在线观看| 欧美成人免费小视频| 亚洲a区在线视频| 亚洲国产精品国自产拍av秋霞| 国产精品久久久久免费a∨大胸| 国语对白做受69| 国产亚洲美女精品久久久| 97欧美精品一区二区三区| 亚洲成年人在线播放| 亚洲专区国产精品| 大胆人体色综合| 国产精品久久久久免费a∨大胸| 欧美视频裸体精品| 亚洲国产精品成人av| 色综合久久久久久中文网| 欧美亚洲激情在线| 91精品国产综合久久香蕉| 精品亚洲一区二区| 亚洲视频在线播放| 久久久www成人免费精品| 欧美一级淫片videoshd| 欧美诱惑福利视频| 久久91精品国产| 日韩电影大片中文字幕| 九九精品视频在线| 欧美日韩美女在线| 欧美黑人xxx| 亚洲自拍欧美色图| 狠狠躁夜夜躁人人爽天天天天97| 亚洲国产欧美一区二区三区久久| 亚洲人a成www在线影院| 日韩大片免费观看视频播放| 国产精品久久久久久久av电影| 欧美一区二区影院| 国产精品日本精品| 最近2019年中文视频免费在线观看| 久久久久久久久爱| 岛国精品视频在线播放| 不卡av在线播放| 日韩精品有码在线观看| 热99精品只有里视频精品| 一区二区三区日韩在线| 国产午夜精品免费一区二区三区| 久久久久亚洲精品| 欧美床上激情在线观看| 欧美激情在线有限公司| 国产精品久久久久影院日本| 久久夜色精品亚洲噜噜国产mv| 国产精品高潮呻吟久久av无限| 国产精品ⅴa在线观看h| 国产成人精品久久二区二区91| 98精品国产高清在线xxxx天堂| 国产一区二区丝袜高跟鞋图片| 久久高清视频免费| 亚洲人成电影网站色www| 久久青草精品视频免费观看| 91av在线网站| 成人精品久久av网站| 欧美乱大交xxxxx另类电影| 国产91在线高潮白浆在线观看| 精品国产老师黑色丝袜高跟鞋| 热门国产精品亚洲第一区在线| 亚洲成av人片在线观看香蕉| 国产人妖伪娘一区91| 亚洲天天在线日亚洲洲精| 亚洲片av在线| 久久久视频在线| 亚洲国产成人精品久久久国产成人一区| 亚洲成**性毛茸茸| 国产不卡av在线免费观看| 欧美激情成人在线视频| 国产午夜精品全部视频播放| 青青精品视频播放| 欧洲日本亚洲国产区| 91av在线视频观看| 成人在线视频福利| 18一19gay欧美视频网站| 久久久精品亚洲| 国产精品久久久久久久美男| 欧美视频免费在线| 亚洲电影av在线| 国产欧美最新羞羞视频在线观看| 韩国美女主播一区| 青青青国产精品一区二区| 97欧美精品一区二区三区| 欧美高清性猛交| 韩国三级日本三级少妇99| 国产亚洲视频中文字幕视频| 亚洲天堂av在线免费观看| 亚洲成人精品av| 亚洲欧洲成视频免费观看|