天天看點

c++和c語言的inline關鍵字對比

其實我一直比較喜歡C語言,對C++的了解少之又少,但是最近由于需要翻看起C++的書籍來。在C++沉思錄當中,看到了這樣一句話:“我還指出,由于這些成員函數定義在Trace類自身的定義内,C++會内聯擴充它們,是以就使得即使在不進行跟蹤的情況下,在程式中保留Trace對象也不必付出許多代價。——Koenig,《C++沉思錄中文版》,page2”。K先生所舉例的代碼如下所示:

1 class 
 2 Trace{
 3 public :
 4            Trace(){noisy = 0;}
 5            void print(char *s){if(noisy) printf("%s,"s);}     
 6            void on(){noisy = 1;}
 7            void off(){noisy = 0;} 
 8 
 9 private:
10            noisy = 1;
11 }      

其實這段代碼風格并不是所提倡的(函數的聲明和定義其實應該分隔開的),當然K先生這裡的目的是舉個例子說明問題。

但是這裡确實引起了我的疑惑,為什麼K先生說“即使在不跟蹤的情況下,在程式中保留Trace對象也不必付出許多代價”?按理說,這種把函數定義直接寫在類内部的方式直接導緻了函數的内聯,而内聯确實膨脹程式,是以我産生了疑惑,這裡先埋下伏筆,在知識梳理完畢後嘗試解惑故。

下面的知識引用自CSDN部落格,http://blog.csdn.net/lidh04/article/details/3795802和http://blog.csdn.net/zhangchao3322218/article/details/8099747。

首先在C語言中也是存在inline的,這裡的說明是針對gcc 編譯器的。在gcc 中,有三種方式的内聯,分别為static inline,inline,extern inline,下面分開介紹:

1.inline。定義的說法:這是一個針對函數定義的關鍵字(注意并非針對聲明),用于對編譯器的建議,當然編譯器有理由拒絕,其作用為不專門為其在調用處産生彙編代碼,隻是像宏那樣進行展開。

注意,以下情況不在上述讨論的範圍内:

一、回調

二、遞歸

例外情況的原因請讀者自行思考。而且,被這樣生命的函數可以在檔案外被調用,像這樣 

extern func();      

但是需要注意的是,不可以出現這種情況:

extern inline function();//這是不對的      

這是我們下面讨論的extern inline,使用情況很狹窄,請注意。

2.static inline 。可以了解為static和inline這兩種屬性的疊加。故而,相對于inline來講,static限制了這種函數隻能在被定義的檔案中使用,不可以被extern。

3.extern inline。這個不能想當然的了解為extern 和 inline 屬性的疊加。實際上,gcc的extern inline 函數隻能被内聯,并不會産生出獨立的彙編代碼,即使出現了上面提到的兩種意外;而且,extern inline 允許在同一個檔案中出現重名函數。

但是我們一般沒有理由使用這樣一種東西,其存在的意義我現在還沒有搞明白。

下面來看一下在C++當中的inline。

其實這兩種語言的的inline很相似的,C++中比C中多的那一部分應該使我們在開篇提到的Class的内部會自動将已經定義好的函數内聯,但是這個并不是值得提倡的。在編譯的時候,inline函數省去了函數調用的開銷(esp,ebp,寄存器資料改變,局部性改變,上下文切換等等),是以規模較小的inline函數會增加性能。

那麼我們回到剛開始的疑惑,嘗試着解答。

回顧一下,我的疑惑是K先生的“在程式中保留Trace對象也不必付出許多代價”,産生疑惑的原因是我對于内聯的了解:在調用處進行函數的展開,導緻程式的膨脹。

但是由于這裡被内聯的函數很小,根本和膨脹談不上關系,在我們不回收Trace對象的時候,也不會産生太大的浪費,也就是K先生所言“代價”。

轉載于:https://www.cnblogs.com/mickey-nan/p/4122297.html