鏈接:https://www.zhihu.com/question/53082910/answer/133612920
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
inline 絕對是C++里最讓人混淆的關鍵詞之一了(比static還過分)。
============== Update 30 Nov 2016
看其他評論里有提到static 的。個人評價一下 static + inline 一起:那就是把死人往活里搞,活人往死里搞的趕腳,坑之深簡直不忍直視。先上追加的3個結論;后面有代碼,有耐心的小伙伴們拿回去自己試。
3. 謹慎使用 static:如果只是想把函數定義寫在頭文件中,用 inline,不要用static。static 和 inline 不一樣:- static 的函數是 internal linkage。不同編譯單元可以有同名的static 函數,但該函數只對 對應的編譯單元 可見。如果同一定義的 static 函數,被不同編譯單元調用,每個編譯單元有自己單獨的一份拷貝,且此拷貝只對 對應的編譯單元 可見。
- inline 的函數是 external linkage,如果被不同編譯單元調用,每個編譯單元引用/鏈接的是同一函數,同一定義。
- 上面的不同直接導致:如果函數內有 static 變量,對inline 函數,此變量對不同編譯單元是共享的(Meyer's Singleton);對於static 函數,此變量不是共享的。看后面的代碼就明白區別了。
4. static inline 函數,跟 static 函數單獨沒有差別,所以沒有意義,只會混淆視聽。
5. inline 函數的定義不一定要跟聲明放在一個頭文件里面:定義可以放在一個單獨的頭文件 .hxx 中,里面需要給函數定義前加上 inline 關鍵字,原因看下面第 2.點;然后聲明 放在另一個頭文件 .hh 中,此文件include 上一個 .hxx。這種用法 boost里很常見:優點1. 實現跟API 分離,encapsulation。優點2. 可以解決 有關inline 函數的 循環調用問題:這個不展開說了,看一個這個文章就懂了:Headers and Includes: Why and How 第 7 章,function inlining。
Reference: inline specifier
============== 原答案30 Nov 2016
1. 不要再把 inline 和編譯器優化掛上關系了,太誤導人。編譯器不傻,inline is barely a request。你不加inline,小函數在開O3時,編譯器也會自動給你優化了。看到inline時,應該首先想到其他用意,在考慮編譯器優化。
2. inline最大的用處是:非template 函數,成員或非成員,把定義放在頭文件中,定義前不加inline ,如果頭文件被多個translation unit(cpp文件)引用,ODR會報錯multiple definition。
============== static / inline 代碼
a.hh
#ifndef A_HH # define A_HH # include <iostream> namespace static_test { static int& static_value() // (!*!) Or change this to inline { static int value = -1; return value; } namespace A { void set_value(int val); void print_value(); } } #endif
a. cc
# include "a.hh" namespace static_test { namespace A { void set_value(int val) { auto& value = static_value(); value = val; } void print_value() { std::cout << static_value() << '\n'; } } }
b.hh:
#ifndef B_HH # define B_HH # include <iostream> namespace static_test { namespace B { void set_value(int val); void print_value(); }; } #endif
b.cc:
# include "a.hh" # include "b.hh" namespace static_test { namespace B { void set_value(int val) { auto& value = static_value(); value = val; } void print_value() { std::cout << static_value() << '\n'; } } }
# include "a.hh" # include "b.hh" int main() { static_test::A::set_value(42); static_test::A::print_value(); static_test::B::print_value(); static_test::B::set_value(37); static_test::A::print_value(); static_test::B::print_value(); return 0; }
- a.hh 中標注 (!*!) 的那行,如果是inline,輸出:42,42,37,37。value 在整個程序中是個Singleton。
- 如果是 static,輸出:42,-1,42,37。value 在不同編譯單元是不同的拷貝,即使它被標注 static。