999精品在线视频,手机成人午夜在线视频,久久不卡国产精品无码,中日无码在线观看,成人av手机在线观看,日韩精品亚洲一区中文字幕,亚洲av无码人妻,四虎国产在线观看 ?

淺談C++中內聯函數的應用

2013-12-31 00:00:00許建宏汪婧
無線互聯科技 2013年11期

摘 要:本文著重探究內聯的優點與局限性,說明什么情況下應該采用、不該采用以及要警惕錯用。

關鍵詞:C語言;C++;內聯函數

對比于C語言的函數,C++增加了重載、內聯、const和virtual四種新機制。其中重載和內聯機制既可用于全局函數也可用于類的成員函數,const與virtual機制僅用于類的成員函數。重載和內聯肯定有其好處才會被C++語言采納,但是不可以當成免費的午餐而濫用。

1 用內聯取代宏代碼

C++語言支持函數內聯,其目的是為了提高函數的執行效率。在C程序中,可以用宏代碼提高執行效率。宏代碼本身不是函數,但使用起來象函數。預處理器用復制宏代碼的方式代替函數調用,省去了參數壓棧、生成匯編語言的CALL調用、返回參數、執行return等過程,從而提高了速度。使用宏代碼最大的缺點是容易出錯,預處理器在復制宏代碼時常常產生意想不到的邊際效應。

例如“#define MAX(a,b) (a)>(b)?(a):(b)”語句“result=MAX(i,j)+2;”將被預處理器解釋為“result=(i)>(j)?(i):(j)+2;”由于運算符‘+’比運算符‘:’的優先級高,所以上述語句并不等價于期望的“result=((i)>(j)? (i):(j))+2;”。如果把宏代碼改寫為“#define MAX(a,b)((a)>(b)?(a):(b))”,則可以解決由優先級引起的錯誤。但是即使使用修改后的宏代碼也不是萬無一失的,例如語句“result=MAX(i++,j);”將被預處理器解釋為“result=(i++)>(j)?(i++):(j);”。對于C++ 而言,使用宏代碼還有另一種缺點,即無法操作類的私有數據成員。

讓我們看看C++的“函數內聯”是如何工作的。對于任何內聯函數,編譯器在符號表里放入函數的聲明。如果編譯器沒有發現內聯函數存在錯誤,那么該函數的代碼也被放入符號表里。在調用一個內聯函數時,編譯器首先檢查調用是否正確。如果正確,內聯函數的代碼就會直接替換函數調用,于是省去了函數調用的開銷。這個過程與預處理有顯著的不同,因為預處理器不能進行類型安全檢查,或者進行自動類型轉換。假如內聯函數是成員函數,對象的地址會被放在合適的地方,這也是預處理器辦不到的。

C++語言的函數內聯機制既具備宏代碼的效率,又增加了安全性,而且可以自由操作類的數據成員。所以在C++程序中,應該用內聯函數取代所有宏代碼,“斷言assert”恐怕是唯一的例外。assert是僅在Debug版本起作用的宏,它用于檢查“不應該”發生的情況。為了不在程序的Debug版本和Release版本引起差別,assert不應該產生任何副作用。如果assert是函數,由于函數調用會引起內存、代碼的變動,那么將導致Debug版本與Release版本存在差異。所以assert不是函數,而是宏。

2 內聯函數的編程風格

關鍵字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與函數定義體放在一起

{

}

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

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

class A

{

public:

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

}

將成員函數的定義體放在類聲明之中雖然能帶來書寫上的方便,但不是一種良好的編程風格,上例應該改成:

// 頭文件

class A

{

public:

void Foo(int x, int y);

}

// 定義文件

inline void A::Foo(int x, int y)

{

}

3 慎用內聯

內聯能提高函數的執行效率,為什么不把所有的函數都定義成內聯函數?但如果所有的函數都是內聯函數,還用得著“內聯”這個關鍵字嗎?

內聯是以代碼膨脹(復制)為代價,僅僅省去了函數調用的開銷,從而提高函數的執行效率。如果執行函數體內代碼的時間,相比于函數調用的開銷較大,那么效率的收獲會很少。另一方面,每一處內聯函數的調用都要復制代碼,將使程序的總代碼量增大,消耗更多的內存空間。以下情況不宜使用內聯:

⑴如果函數體內的代碼比較長,使用內聯將導致內存消耗代價較高。

⑵如果函數體內出現循環,那么執行函數體內代碼的時間要比函數調用的開銷大。

類的構造函數和析構函數容易讓人誤解成使用內聯更有效。要當心構造函數和析構函數可能會隱藏一些行為,如“偷偷地”執行了基類或成員對象的構造函數和析構函數。所以不要隨便地將構造函數和析構函數的定義體放在類聲明中。一個好的編譯器將會根據函數的定義體,自動地取消不值得的內聯,這也進一步說明了inline不應該出現在函數的聲明中。

C++語言中的內聯展現了很多優點,但是這些優點的背后都隱藏著一些隱患。正如人們的飲食,少食和暴食都不可取,應當恰到好處。我們要辨證地看待C++的一些新機制,應該恰如其分地使用它們。雖然這會使我們編程時多費一些心思,少了一些痛快,但這才是編程的藝術。

主站蜘蛛池模板: 99热在线只有精品| 婷婷在线网站| 91久久精品日日躁夜夜躁欧美| 国内精品自在欧美一区| 永久成人无码激情视频免费| 亚洲第一视频网站| 99成人在线观看| 亚洲国产中文欧美在线人成大黄瓜| 色九九视频| 精品欧美日韩国产日漫一区不卡| 黑人巨大精品欧美一区二区区| 理论片一区| 在线不卡免费视频| 91小视频版在线观看www| 欧美精品成人一区二区视频一| a国产精品| 日本道中文字幕久久一区| 国产成人精品无码一区二| 国产精品视频a| 福利国产在线| 久久精品电影| 久久亚洲高清国产| 高h视频在线| 最新亚洲人成网站在线观看| 韩日无码在线不卡| 国产主播在线观看| 亚洲制服中文字幕一区二区| 免费A级毛片无码无遮挡| 亚洲天堂成人| 亚洲最大福利网站| 国产精品制服| 国产精品永久不卡免费视频| 免费中文字幕一级毛片| 福利一区三区| 色亚洲成人| 亚洲欧美极品| 久久窝窝国产精品午夜看片| 无码中文AⅤ在线观看| 青青青视频91在线 | 91国语视频| 色婷婷视频在线| 亚洲综合色婷婷| 一本色道久久88| 超清人妻系列无码专区| 日本福利视频网站| 女人av社区男人的天堂| 99热国产这里只有精品9九| 国内99精品激情视频精品| 中文毛片无遮挡播放免费| 91 九色视频丝袜| 国产精品亚洲综合久久小说| 成人精品在线观看| 亚洲日产2021三区在线| 精品自拍视频在线观看| 久久熟女AV| 欧美福利在线观看| 欧美无遮挡国产欧美另类| 九九精品在线观看| 重口调教一区二区视频| 噜噜噜久久| 精品黑人一区二区三区| 午夜天堂视频| 在线国产91| 国产免费羞羞视频| 老熟妇喷水一区二区三区| 国产精品久久久精品三级| AV不卡无码免费一区二区三区| 成人在线观看不卡| 亚洲啪啪网| 国产精品免费p区| 亚洲国产成人精品无码区性色| 久久国产高清视频| 亚洲婷婷在线视频| 青青青伊人色综合久久| 波多野结衣一级毛片| 中文字幕欧美日韩高清| 青青青伊人色综合久久| 一个色综合久久| 国产噜噜噜视频在线观看| 91午夜福利在线观看精品| 精品伊人久久久大香线蕉欧美| 日韩福利在线视频|