1.前言 C++中包含頭文件存在兩種不同的形式,尖括弧<>和雙引號"",其區別在於搜索範圍和搜索順序。 以Visual Studio 2022為例,我們創建一個工程,在裡面添加主函數main.cpp的文件,以及頭文件test.h Project ├── main.cpp └── test.h 2.搜 ...
1.前言
C++中包含頭文件存在兩種不同的形式,尖括弧<>和雙引號"",其區別在於搜索範圍和搜索順序。
以Visual Studio 2022為例,我們創建一個工程,在裡面添加主函數main.cpp的文件,以及頭文件test.h
Project
├── main.cpp
└── test.h
2.搜索範圍
<>只可以訪問 系統目錄下的頭文件(.h),""可以訪問 當前文件相對路徑 + 系統目錄下的頭文件(.h) 。
使用#include <>系統會只會顯示並搜索系統目錄里的頭文件。
因此#include <test.h>會報錯。
#include <test.h> // 錯誤,在標準庫內找不到test.h文件
使用#include ""系統會顯示當前目錄下的文件,但實際上也是可以包含系統目錄裡頭文件的,只不過在編譯器內沒有顯示而已。
由於test.h是我們在工程當中新創建的頭文件,且位於main.cpp同一目錄下,只能使用#include "test.h"來包含該文件。
#include "test.h" // Project\test.h
3.添加包含目錄
通常我們的源碼不可能全部在同一目錄下,這樣不利於代碼後續的維護,可讀性也會變得非常糟糕,因此需要添加包含目錄。例如將整個工程源碼的最外層添加進來,這樣後續所有的include都可以從工程的入口找到對應的頭文件源碼。
對於Visual Studio,在 項目->屬性->配置屬性->C/C++->常規->附加包含目錄。
4.搜索順序
附加包含目錄允許添加多個,且C++也允許包含相同名字的頭文件。
這樣就會帶來一個問題,如果相同地址下存在相同名字的頭文件,會出現頭文件包含錯誤的問題,這是由沒搞清#inlcude包含順序所導致。
首先給出搜索順序的結論:
#inlcude <> 從包含目錄開始,按照順序依次查找,最後到系統目錄。
#include "" 從當前目錄開始,然後是包含目錄,按照順序依次查找,最後到系統目錄。
常見的幾個問題,以如下文件結構舉例,addr1和addr2是文件夾名稱,都添加進附加包含目錄內。
Project
├── main.cpp
├── addr1
├── test.h
├── addr2
├── test.h
└── test.h
1.某個同名頭文件存在於多個包含目錄的相同地址下,那麼在搜索路徑排在後面的文件就不會被包含,例如:
addr1和addr2都被添加進附加包含目錄,那麼對於main.cpp來說,addr2下的test.h就沒有辦法被直接包含。
2.由於搜索優先順序的原因,會導致<>和""所包含的頭文件不同,使用時應當註意。
#include <test.h> // Project\addr1\test.h
#include "test.h" // Project\test.h
通常儘可能少的將亂七八糟的地址添加進目錄當中,例如只將整個工程的源碼入口加入到附加包含目錄,或者從更改命名規範上來屏蔽這類問題。
5.總結
搜索空間上: #include "" 大於 #inlcude <>,因為#include "" 總是會搜索當前路徑。
搜索順序上: #inlcude <> 總是從包含目錄開始,#inlcude "" 總是從當前目錄開始,然後搜索包含路徑,兩種搜索方式總是在找到對應文件的那一刻停止。
對於那些既可以使用""也可使用<>編譯的頭文件,例如標準庫文件,建議使用<>,而當前目錄下的文件可以省去前面的長串相對地址,這樣可以在一定程度上提高代碼的編譯效率。