不要在標頭檔案中定義有鏈結的實體

2021-06-09 07:10:31 字數 898 閱讀 8537

具有鏈結的實體,包括名字空間級的變數或函式,都需要分配記憶體,在標頭檔案中定義這樣的實體將導致連線錯誤或者記憶體浪費。所以,應該將所有具有鏈結的實體放入實現檔案。

下面的標頭檔案:

1

intmax;

2string hello("

hello, world!");

3void fun()

只要被乙個以上的原始檔所包含,就很容易導致鏈結錯誤,編譯器會報告存在重複符合錯誤。原因很簡單:每個原始檔中,都會定義max、hello和fun的函式體,並分配空間。當進行鏈結的時候,鏈結器將面對多個具有相同名字而且互相在競爭的符號。

解決之道非常簡單——只在標頭檔案中放置宣告即可:

1

extern

max;

2extern

string

hello;

3void fun();

而實際的定義則放在乙個實現檔案中。

同樣,不要在同檔案中定義名字空間級的static實體,例如:

1

static

intmax;

2static

string hello("

hello, world!");

3static

void fun()

這種對static的錯誤使用比在標頭檔案中只定義全域性實體還要危險。對於全域性實體,至少鏈結器可能會立即發現重複,但是靜態資料和函式的重複是合法的。因此,若在某個標頭檔案中定義了靜態資料和靜態函式,而該標頭檔案要被50個檔案包含,那麼函式體和資料所占用的空間在最終的可執行檔案中會重複50次,造成記憶體浪費。博文**

例外情況:

(1)內聯函式。

(2)函式模版。

(3)類模板的靜態資料成員。

為什麼模板函式的定義也要在標頭檔案裡

對於模板,最重要的一點,就是在定義它的時候,編譯器並不會對它進行編譯,因為它沒有乙個實體可用。只有模板被具體化 specialization 之後 用在特定的型別上 編譯器才會根據具體的型別對模板進行編譯。所以才定義模板的時候,會發現編譯器基本不會報錯,也做不出智慧型提示。但是當它被具體用在乙個類上...

標頭檔案中防止重複定義的巨集

我是個有 潔癖 的人,不願意與警告為伍,哪怕是只有乙個,也會讓我渾身上下都不舒服。在一次整改乙個嵌入式arm工程源 的過程中,乙個編譯告警迷惑了我,費了我不少時間。waring c2207w inventing extern inituartpos main.c line 87 按理說不應該出現這種...

inline函式的定義放在標頭檔案中

inline是加在實現上,就算加在宣告上,編譯器也會忽略掉。內聯展開是在編譯時進行的,只有鏈結的時候原始檔之間才有關係。所以內聯要想跨原始檔必須把實現寫在標頭檔案裡。如果乙個 inline 函式會在多個原始檔中被用到,那麼必須把它定義在標頭檔案中。注意 將函式的定義 之間的部分 放在標頭檔案中是強制...