static inline 和 extern inline 的含義

來源:互聯網
上載者:User

問:

首先,關於inline就夠煩人了,有的書上說inline關鍵字要加在定義前,聲明時可以省略,有的說聲明時加上inline函數就變成內聯型,
有的說聲明和定義形式要保持一致。在一個類中聲明一個函數,函數的實現在外部,無論是僅僅在內部聲明處加inline,還是在外部實現處加inline,
或是兩個地方都加,編譯均能通過,而且也無法通過調試的辦法看出對程式到底有啥影響。搞不清到底要怎麼寫這個inline才比較好,不過可以肯定的
是,inline函數的定義部分要放在標頭檔裡,聲明和定義分開放會編譯出錯。

而且inline還可以和extern關鍵字、static關鍵字合用,在網上搜了一下,linux之父linus說過 "static
inline" means "we have to have this function, if you use it, but don't
inline it, then make a static version of it in this compilation unit".
"extern inline" means "I actually _have_ an extern for this function,
but if you want to inline it, here's the inline-version".
這話說的雲裡霧裡的,誰能解釋一下,說說你對static inline 和 extern inline用法的理解。

答:

extern inline表示該函數是已聲明過的了.由於函數本身可以聲明多次,所以extern對函數的影響僅僅把函數的隱藏屬性顯式化了.
extern 對於非函數的對象是有用的,因為對象聲明時會帶來記憶體的分配,而用 extern就表示該對象已經聲明過了,不用再分配記憶體.
static是以前C的用法.目的是讓該關鍵字標識的函數只在本地檔案可見,同一個程式的其它檔案是不可見該函數的.換句話說,就算你其它檔案裡包含了同名同參數表的函數定義的話,也是不會引起函數重複定義的錯誤的.因為static是僅在當前檔案可見.

關於inline函數,你說的大部分的都 是對的.我來給你總結一下吧.
inline函數僅僅是一個建議,對編譯器的建議,所以最後能否真正內聯,看編譯器的意思,它如果認為你的函數不複雜,能在調用點展開,就會真正內聯,並不是說聲明了內聯就會內聯,你聲明內聯只是一個建議而已.
其次,因為內嵌函式要在調用點展開,所以編譯器必須隨處可見內嵌函式的定義,要不然,就成了非內嵌函式的調用了.所以,這要求你的每個調用了內嵌函式的文
件都出現了該內嵌函式的定義,因此,將內嵌函式放在標頭檔裡實現是合適的,省卻你為每個檔案實現一次的麻煩.而你所以聲明跟定義要一致,其實是指,如果你
在每個檔案裡都實現一次該內嵌函式的話,那麼,你最好保證每個定義都是一樣的,否則,將會引起未定義的行為,即是說,如果不是每個檔案裡的定義都一樣,那
麼,編譯器展開的是哪一個,那要看具體的編譯器而定.所以,最好將內嵌函式定義放在標頭檔中.
而類中的成員函數預設都是內聯的,如果你在類定義時就在類內給出函數,那當然最好.如果你在類中未給出成員函數定義,而你又想內聯該函數的話,那在類外要
加上inline,否則就認為不是內聯的.而且剛說了,內嵌函式最好放在標頭檔內,所以最好在類定義的標頭檔裡把類的內嵌函式都實現了.
而你說的將聲明與實現分開,其實是不會編譯出錯的,反正我寫那麼多程式都沒試過.將聲明與定義分開的話,這樣的後果會帶來編譯器並不隨處可見該函數定義,所以,只能在你實現定義的那個檔案裡,將該函數看成內聯(如果可以內聯的話),在其它檔案,仍看成是普通函數.
看到這裡,我想你應該明白了.那麼聲明時加inline,實現時要不要加inline呢?呵呵,留給 lz 思考吧.
    extern inline表示該函數是已聲明過的了.由於函數本身可以聲明多次,所以extern對函數的影響僅僅把函數的隱藏屬性顯式化了.
extern 對於非函數的對象是有用的,因為對象聲明時會帶來記憶體的分配,而用 extern就表示該對象已經聲明過了,不用再分配記憶體.
static是以前C的用法.目的是讓該關鍵字標識的函數只在本地檔案可見,同一個程式的其它檔案是不可見該函數的.換句話說,就算你其它檔案裡包含了同名同參數表的函數定義的話,也是不會引起函數重複定義的錯誤的.因為static是僅在當前檔案可見.

關於inline函數,你說的大部分的都 是對的.我來給你總結一下吧.
inline函數僅僅是一個建議,對編譯器的建議,所以最後能否真正內聯,看編譯器的意思,它如果認為你的函數不複雜,能在調用點展開,就會真正內聯,並不是說聲明了內聯就會內聯,你聲明內聯只是一個建議而已.
其次,因為內嵌函式要在調用點展開,所以編譯器必須隨處可見內嵌函式的定義,要不然,就成了非內嵌函式的調用了.所以,這要求你的每個調用了內嵌函式的文
件都出現了該內嵌函式的定義,因此,將內嵌函式放在標頭檔裡實現是合適的,省卻你為每個檔案實現一次的麻煩.而你所以聲明跟定義要一致,其實是指,如果你
在每個檔案裡都實現一次該內嵌函式的話,那麼,你最好保證每個定義都是一樣的,否則,將會引起未定義的行為,即是說,如果不是每個檔案裡的定義都一樣,那
麼,編譯器展開的是哪一個,那要看具體的編譯器而定.所以,最好將內嵌函式定義放在標頭檔中.
而類中的成員函數預設都是內聯的,如果你在類定義時就在類內給出函數,那當然最好.如果你在類中未給出成員函數定義,而你又想內聯該函數的話,那在類外要
加上inline,否則就認為不是內聯的.而且剛說了,內嵌函式最好放在標頭檔內,所以最好在類定義的標頭檔裡把類的內嵌函式都實現了.
而你說的將聲明與實現分開,其實是不會編譯出錯的,反正我寫那麼多程式都沒試過.將聲明與定義分開的話,這樣的後果會帶來編譯器並不隨處可見該函數定義,所以,只能在你實現定義的那個檔案裡,將該函數看成內聯(如果可以內聯的話),在其它檔案,仍看成是普通函數.
看到這裡,我想你應該明白了.那麼聲明時加inline,實現時要不要加inline呢?呵呵,留給 lz 思考吧.

 

 

呵呵,你看的還是英文版的哦.你理解的不是這樣,放在標頭檔中不是只存在一個定義,而是只要包含了該標頭檔的程式文字檔都存在了這個定義.而inline函數是可以被重複定義的,在C++中,常量對象跟內嵌函式都是可以多次定義的.
你要把函數那章都看完就會明白.
我先假設你的函數符合內聯的條件.
在聲明是加inline,定義時不加,則要求編譯器編譯時間,能看到inline的聲明,而且在展開點看到該定義,這樣,就將其視為內嵌函式.
如果你聲明沒有inline,卻在定義時inline了.這時,如果其它要調用該函數的檔案看到了它的聲明,就認為該函數不是內聯的,所以,到了調用處,
轉到該函數實現的地方,卻意外地看到了inline聲明,這時,會導致連結出錯.若要改正的話,就要讓調用該函數的檔案也看到有inline的定義,而不
是在調用時才看到.你可以在每個檔案都加上有inline的定義.(如果不加inline,則會出現重複定義的錯誤,因為內嵌函式才可以被重複定義).或
者另一種修改方法,你將定義時的inline去掉,這樣就成為普通函數,連結不會出錯.如果是前一種改法,仍是內聯的,因為符合了看到了inline且隨
處可見其定義的條件.
如果你將聲明跟定義都放在同一個標頭檔,而在聲明時不內聯,在實現時內聯,這樣編譯器也是將該函數內聯(符合兩個條件,看到inline的聲明(雖然是在定義時),隨處可見其定義).
總結說來,只要編譯器看到有inline出現,而且定義隨處可見,就能將函數內聯(上邊已假設你的函數足夠簡單可以內聯),而不必管是定義還是聲明加inline的問題.
所以,為了方便,將內嵌函式直接聲明時就定義,放在標頭檔中.這樣其它檔案包含了該標頭檔,就在每個檔案都出現了內嵌函式的定義.就可以內聯了.
類的成員函數也一樣.只不過,類的成員函數預設都是內聯的,前提是你要在類定義時提供成員函數定義.如果在類定義時不提供函數定義,則要在類外邊加上inline,否則將視為普通函數.
關於這些,你看了C++primer有關函數那章自然會明白的.
呵呵,你看的還是英文版的哦.你理解的不是這樣,放在標頭檔中不是只存在一個定義,而是只要包含了該標頭檔的程式文字檔都存在了這個定義.而inline函數是可以被重複定義的,在C++中,常量對象跟內嵌函式都是可以多次定義的.
你要把函數那章都看完就會明白.
我先假設你的函數符合內聯的條件.
在聲明是加inline,定義時不加,則要求編譯器編譯時間,能看到inline的聲明,而且在展開點看到該定義,這樣,就將其視為內嵌函式.
如果你聲明沒有inline,卻在定義時inline了.這時,如果其它要調用該函數的檔案看到了它的聲明,就認為該函數不是內聯的,所以,到了調用處,
轉到該函數實現的地方,卻意外地看到了inline聲明,這時,會導致連結出錯.若要改正的話,就要讓調用該函數的檔案也看到有inline的定義,而不
是在調用時才看到.你可以在每個檔案都加上有inline的定義.(如果不加inline,則會出現重複定義的錯誤,因為內嵌函式才可以被重複定義).或
者另一種修改方法,你將定義時的inline去掉,這樣就成為普通函數,連結不會出錯.如果是前一種改法,仍是內聯的,因為符合了看到了inline且隨
處可見其定義的條件.
如果你將聲明跟定義都放在同一個標頭檔,而在聲明時不內聯,在實現時內聯,這樣編譯器也是將該函數內聯(符合兩個條件,看到inline的聲明(雖然是在定義時),隨處可見其定義).
總結說來,只要編譯器看到有inline出現,而且定義隨處可見,就能將函數內聯(上邊已假設你的函數足夠簡單可以內聯),而不必管是定義還是聲明加inline的問題.
所以,為了方便,將內嵌函式直接聲明時就定義,放在標頭檔中.這樣其它檔案包含了該標頭檔,就在每個檔案都出現了內嵌函式的定義.就可以內聯了.
類的成員函數也一樣.只不過,類的成員函數預設都是內聯的,前提是你要在類定義時提供成員函數定義.如果在類定義時不提供函數定義,則要在類外邊加上inline,否則將視為普通函數.
關於這些,你看了C++primer有關函數那章自然會明白的.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.