Re: [問題] 全域變數宣告方式

看板C_and_CPP作者 (purpose)時間9年前 (2014/08/28 01:03), 9年前編輯推噓2(204)
留言6則, 5人參與, 最新討論串2/2 (看更多)
: 另外偷渡一個問題 最近看到一個.h : 有一個函數 static inline void function(); : static 不是local scope 又宣告在.h 讓人call 這有什麼好處嗎?? 如同 C++ Primer 所說:「inline 函式應該定義於表頭檔內」,所以不再多講。 比較值得注意的是,為什麼 static inline? 我們知道一個事實「inline 只是對編譯器的請求,可能被忽略」, 當 inline 被拒絕行內擴展時,他的性質就跟 non-inline 函數一樣。 又 C++ 的世界裡,有個「One Definition Rule」, 使得函數通常都不能被重複定義,否則會違反 ODR, 因此 inline 函數,理論上,也需要考慮重複定義的問題。 最初的 inline 函數,其 default linkage 其實是 static。 也就是說以前 inline void function() 跟 static inline void function() 等價。 現代的 C++ 才將 inline 函數 default linkage 改成 external。 那麼猜測原問題中,寫 static inline 應該是衝著 static linkage 而來。 ######################################################### static inline 相較於 extern inline 來說,有以下優缺點。 優點: (1) 當某個 static inline 函數,於多個 *.cpp 檔有不同實作時, 依然不違反 ODR。 ※ 附註:相同狀況換成 extern inline 就會違反 ODR, 根據 C++ 標準,這是未定義行為,實際在 VC++ 的作法是 pick any。也就是可能挑 1.cpp 裡面的實作當代表,也可能 挑選 2.cpp 的實作來當這個 inline 函數的代表,整個程式 中所有用到該 inline 的地方,都會使用該代表的版本。 (2) 當某個 satic inline 函數有不同的實作時, 不論有沒有被 compiler 行內擴展, 程式計算的結果都不會改變,是固定可預期的。 缺點: 當 static inline 函數內部,出現 local static variable 時, 程式計算的結果是難以預期的。 用以下案例來重現此問題: ========================================================= // 檔案 1.cpp #include <stdio.h> void call_2(); static inline int foo() { static int counter = 0; return ++counter; } int main() { printf("counter = %d\n", foo()); printf("counter = %d\n", foo()); call_2(); return 0; } ========================================================== // 檔案 2.cpp #include <stdio.h> static inline int foo() { static int counter = 0; return ++counter; } void call_2() { printf("in 2, counter = %d\n", foo()); } =========================================================== 則上述程式的執行結果為: =========================================================== counter = 1 counter = 2 in 2, counter = 1 =========================================================== 除非使用 extern inline,才能得到「in 2, counter = 3」這個預期的結果。 總結來說,只要保持 inline 函數的實作一致,永遠不出現衝突的版本,就不需要 依賴 static inline 的優點 (1) (2)。 也最好永遠不要在 inline 函數內,使用 static variable。 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 124.8.129.83 ※ 文章網址: http://www.ptt.cc/bbs/C_and_CPP/M.1409158998.A.E28.html ※ 編輯: purpose (124.8.129.83), 08/28/2014 01:05:40 ※ 編輯: purpose (124.8.129.83), 08/28/2014 01:07:49

08/28 01:22, , 1F
再不然就根本不要管inline 反正編譯器大概會無視他
08/28 01:22, 1F

08/28 01:24, , 2F
只有在學校練習時用過 inline
08/28 01:24, 2F

08/28 08:01, , 3F
原來還有這招 不過我自己連inline都沒宣告過== 謝謝分享!
08/28 08:01, 3F

08/28 09:10, , 4F
inline裡面邏輯不要太複雜,連static local都出現的話
08/28 09:10, 4F

08/28 09:10, , 5F
通常也代表這個inline一點都不該inline了
08/28 09:10, 5F

08/28 20:07, , 6F
突然想起 M$ 的部份 inline 似乎還會拆檔寫...
08/28 20:07, 6F
文章代碼(AID): #1J_WzMue (C_and_CPP)
文章代碼(AID): #1J_WzMue (C_and_CPP)