清除 Visual Studio 中的 C/C++ 包含

從 Visual Studio 17.8 Preview 1 開始,Visual Studio 提供 #include 清除功能,以下列方式改善程式碼的品質:

  • 僅因為需要標頭檔會由另一個標頭檔間接包含,因此提供新增程式碼的標頭檔。
  • 移除未使用的標頭檔 -- 改善建置時間和程式碼清潔的供應專案。

Include Cleanup 預設為開啟。 若要瞭解如何進行設定,請參閱 在 Visual Studio 中設定 C/C++ Include Cleanup。

直接與間接標頭

首先,一些術語:

  • 直接標頭是您明確 #include 在程式碼中的標頭。
  • 間接標頭是您未明確 #include 表示的標頭。 相反地,您直接包含的標頭檔會包含它。 我們也表示包含 transitively 間接標頭。

包含清除會分析您的程式碼,並判斷未使用哪些標頭,以及哪些標頭會間接包含。 請考慮下列標頭檔:

// myHeader.h

#include <string>
#include <iostream>

void myFunc()
{
    std::string s = "myFunc()\n";
    std::cout << s;
}

以及使用它的程式:

// myProgram.cpp
#include "myHeader.h"

int main()
{
    std::string s = "main()"; // string is indirectly included by myHeader.h
    std::cout << s; // cout is indirectly included by myHeader.h
    myFunc();
}

myHeader.h 是直接標頭,因為 myProgram.cpp 明確包含它。 myHeader.h 包含 <string><iostream> ,因此這些是間接標頭。

問題是 myProgram.cpp 使用 std::stringstd::cout ,但不直接包含定義它們的標頭。 此程式碼會發生編譯,因為 myHeader.h 包含這些標頭。 此程式碼很脆弱,因為如果 myHeader.h 曾經停止包含其中一個程式碼, myProgram.cpp 就不會再編譯。

根據 C++ 指導方針,最好明確包含所有相依性的標頭,讓您的程式碼不受標頭檔變更所造成的脆弱。 如需詳細資訊,請參閱 C++ 核心指導方針 SF.10

包含清除會分析您的程式碼,以識別未使用和間接包含的標頭。 它會根據 Visual Studio 中設定 C++ #include 工具中所述 的設定提供意見反應。 意見反應可以是錯誤清單警告、建議等形式。如需 Include Cleanup 所提供意見反應的詳細資訊,請參閱 包含清除訊息

未使用的標頭

隨著程式碼的發展,您可能不再需要一些標頭檔。 這很難在複雜的專案中追蹤。 一段時間後,您的組建可能需要更長的時間,因為編譯器正在處理不必要的標頭檔。 包含清除可協助您尋找和移除未使用的標頭。 例如,如果在 myFunc()myProgram.cpp 加上批註,該怎麼辦:

// myProgram.cpp
#include "myHeader.h"

int main()
{
    std::string s = "main()"; // string is indirectly included from myHeader.h
    std::cout << s; // cout is indirectly included from myHeader.h
    // myFunc(); // directly included from myHeader.h
}

在下列螢幕擷取畫面中, #include "myHeader.h" 會呈現暗灰色(Visual Studio 中設定 C++ #include 工具中所述 的設定),因為它不會因為已批註而使用 myFunc()

將游標暫留在暗灰色 #include 上方,以顯示快速動作功能表。 按一下燈泡(或選擇 [ 顯示潛在修正連結 ] 以查看與未使用檔案相關的動作:

Three refactoring options are shown: Remove # include myHeader.h, remove all unused includes, and Add all transitively used and remove all unused # includes.

新增可轉移使用的標頭

我們可以選擇移除未使用的標頭檔,但這會中斷程式碼,因為 <string><iostream> 是透過 myheader.h 間接包含。

相反地,我們可以選擇 [ 新增所有可轉移使用的] 並移除所有未使用 #includes 。 這會移除未使用的標頭 myHeader.h ,但也會新增透過 間接包含 myHeader.h 的任何標頭。 在此情況下,結果會將 和 #include <iostream> 新增 #include <string>myProgram.cpp ,並移除 #include "myHeader.h"

// myProgram.cpp
#include <iostream>
#include <string>

int main()
{
    std::string s = "main()"; // string is directly included from <string>
    std::cout << s; // cout is directly included from <string>
    // MyFunc();
}

此工具不會更新批註,但您可以看到程式碼現在使用 且直接使用 std::stringstd::cout 此程式碼不再脆弱,因為它不相依 myHeader.h 于包含其他必要標頭。

最佳做法

請勿移除看似未使用標頭檔的內容,而不先新增間接包含的標頭檔。 這是因為您的程式碼可能依賴間接包含在未使用的標頭檔中。 先新增可轉移使用的標頭。 然後,當您移除未使用的標頭時,由於已移除標頭檔間接包含的標頭檔遺失,所以不會收到編譯錯誤。

若要這樣做,其中一種方法是設定 [新增遺漏的包含 建議層級] 的建議層級 工具 > 選項 > 文字編輯器 > C/C++程式 > 代碼清除)。 此外,將 [移除未使用的包含建議] 的建議層級 設定為 [建議 ]。 接下來:

  1. 在錯誤清單中,確定篩選準則設定為 [建置 + IntelliSense ]。
  2. 尋找「來自 #include x 的內容用於此檔案中並暫時包含」的實例。
  3. 將游標暫留在具有建議的行上。 從燈泡下拉式清單中,選取 [ 新增所有可轉移使用的包含 ]。
  4. 重複專案中的這些步驟,直到解決所有有關可轉移包含的建議為止。
  5. 移除未使用的 include:在錯誤清單中,尋找 「#include x 未用於此檔案」的實例。
  6. 將游標暫留在未使用的標頭上。 從燈泡下拉式清單中,選取 [ 移除所有未使用的專案]。
  7. 重複專案中的這些步驟,直到解決所有 Include Cleanup 建議為止。

在此簡短概觀中,您已瞭解 Include Cleanup 如何協助您移除未使用的標頭,以及新增間接包含的標頭。 這可協助您保持程式碼乾淨、可能更快速地建置,並減少程式碼的脆性。

另請參閱

在 Visual Studio 中設定 C/C++ Include Cleanup
包含清除訊息