跳轉到主要內容
本主題說明我們針對 XBOX 上的 Microsoft Game Development Kit (GDK) 開發所建議的各種 Visual C++ 編譯器與連結器參數。
對於 clang/LLVM for Windows,相同的參數可透過「類似 MSVC」的 clang-cl 前端提供支援。下文會註明幾個 clang 工具組特有的參數。

C++ 語言標準 (/std)

Visual C++ 預設為 C++14 一致性模式。若要啟用 C++17 一致性模式,請使用 /std:c++17。XBOX 上的 Microsoft Game Development Kit (GDK) API 需要 C++11 或更新版本,而遊戲開發完全支援使用 C++14 或更新版本。
/std:c++latest 會為 Visual Studio 2017 與 Visual Studio 2019 啟用 C++20 草案一致性。由於 /std:c++latest 的行為會隨 Visual C++ 服務更新持續變更,因此使用時應謹慎。
VS 2019 (16.11) 與 VS 2022 支援 /std:c++20 參數。請參閱此部落格文章。
從 VS 2019 (16.8) 開始,Visual C++ 編譯器支援 /std:c11 與 /std::c17。不過,GameRuntime 與許多其他 GDK 標頭需要 C++11 或更新版本。
如需詳細資訊,請參閱下列內容:

一般最佳化使用 /O1 /Oi,「熱門」模組使用 /O2

對於 XBOX One 與 XBOX Series X/S 上的亂序執行 CPU,讓程式碼區段能放進指令快取,通常比使用絕對最快版本的程式碼更重要,因此偏好針對空間最佳化。請只為特定模組或函式保留針對時間最佳化的使用。對遊戲而言,產生內建函式值得付出額外的程式碼,因為它可以改善浮點效能。您也可以使用 #pragma optimize("t", on) / #pragma optimize("", on ) 包圍特定函式或函式集合,以對其啟用針對時間最佳化。請記住,由於積極的迴圈展開,針對時間最佳化 (/O2 或 /Ox) 可能會導致程式大小大幅增加。
單一指令多重資料 (SIMD) 自動向量化最佳化只會針對 /O2 或 /Ox 啟用。分析導引最佳化 (PGO) 可以更精確地選擇要在何處套用針對時間最佳化或針對空間最佳化。基於歷史因素,請務必注意,/Ox 幾乎與 O2 相同,但缺少 /GF (消除重複的字串) 與 /Gy (啟用函式層級連結)。因此,一般而言您應該優先使用 /O2 而非 /Ox。如果您使用 /Ox,請務必至少明確啟用 /Gy,這對於啟用連結器最佳化很重要。

/fp:fast 編譯器參數

Visual Studio 2005 引進的 /fp 旗標控制編譯器使用的各種浮點模型 (fast、precise、strict、except)。fast 浮點模型使用許多不屬於核心 “C” 規則的最佳化。precise 浮點模型會停用這些額外的最佳化,且為預設值。我們建議遊戲使用 /fp:fast。 如需詳細資訊,請參閱下列內容: 另請參閱 VS 2022 新增的這些其他浮點相關旗標:

/arch 編譯器參數

x64 原生平台的隱含預設值為 /arch:SSE2。對於 XBOX One 主機 (AMD Jaguar CPU),您應該使用 /arch:AVX。對於 XBOX Series X/S (AMD Hercules CPU),我們建議使用 /arch:AVX2。 使用 /arch:AVX 或 /arch:AVX2 的主要好處是,它會使編譯器產生 SSE 指令的 VEX 前置詞版本,這些版本使用非破壞性的 3 運算元編碼,而不是其中一個來源運算元會被結果覆寫的標準 2 運算元編碼。這會同時影響使用 SSE 指令之 x64 原生程式碼的純量浮點,以及 SSE 內建函式的明確使用。這有助於降低暫存器排程壓力,並可消除部分 movaps 指令。 如需詳細資訊,請參閱下列內容: 對於使用 Visual Studio 2019 (16.3) 或更新版本的 XBOX Series X|S,您也應該使用 /d2vzeroupper,以針對 AMD Hercules CPU 偏好的 vzeroupper 指令使用行為進行最佳化。對於全程式最佳化 (/LTCG),所需的對等連結器參數為 /d2:-vzeroupper。這是 VS 2022 編譯器的預設行為。 對於使用 Visual Studio 2022 的 XBOX One,您也應該使用 /d2vzeroupper-,以針對 AMD Jaguar CPU 偏好的 vzeroupper 指令使用行為進行最佳化。對於全程式最佳化 (/LTCG),所需的對等連結器參數為 /d2:-vzeroupper-。這是 VS 2019 編譯器的預設行為。
對於 clang/LLVM,XBOX One (AMD Jaguar CPU) 請使用 -march=btver2,XBOX Series X/S (AMD Hercules CPU) 請使用 -march=znver2。
對於 PC 開發,您可以確信所有 x64 原生 CPU 都支援 SSE 與 SSE2,因為這是架構定義的一部分。您也可以放心要求 SSE3,因為 Windows 10 或 Windows 11 支援的所有現代 Intel CPU 都支援 SSE3。對於 PC 上 SSE2 以外使用的任何功能 (例如 AVX 或 AVX2),請務必進行執行階段 CPU 支援檢查。

/favor 編譯器參數

/favor 參數控制 x64 編譯器針對 AMD64 與 Intel 64 處理器的最佳化選擇。進行 XBOX 開發時,請使用 /favor:AMD64。

例外狀況處理模型 (/EHsc)

對於 x64 原生程式碼,例外狀況處理對函式結語或序言沒有任何直接的程式碼影響。Windows x86 使用的是以堆疊為基礎的配置,涉及插入模組中的額外程式碼,而 x64 原生程式碼產生則使用以表格為基礎的配置,以確保在例外狀況處理期間能正確回溯堆疊。x64 原生所使用的以表格為基礎配置還有一個優點:它更安全,因為不會受到堆疊緩衝區溢位攻擊。此設計有許多影響。
  • 例外狀況處理不會影響所產生程式碼中的指令數量。雖然 Windows x86 所使用的以堆疊為基礎配置可能會導致 5-10% 的程式碼負擔,但 x64 原生例外狀況處理只會產生與可執行檔相關聯的表格型資料,而不會產生更多指令。即使明確停用 x64 原生的例外狀況處理 (我們不建議這麼做),也只會節省少量用於 C++ 處理的輔助資料,且不會停用堆疊回溯資料的產生。
  • Try/catch 區塊的使用成本低廉。在以堆疊為基礎的配置中,try/catch 區塊會新增一些用於追蹤的額外程式碼。在 x64 上,這只會在回溯表格中新增更多項目。
  • 例外狀況處理 (也就是實際擲回例外狀況) 需要一些額外的表格查詢。其取捨在於,以堆疊為基礎的配置雖然可以更快地擲回例外狀況,但代價是所有程式碼路徑都有額外負擔。以表格為基礎的配置在「擲回」時較慢,但不會影響其他程式碼路徑。由於例外狀況不應用於一般流程控制,事實上應該只在例外情況下觸發,因此與整體應用程式效能相比,這項額外的處理效能成本可以忽略不計。
XBOX 上的 Microsoft Game Development Kit (GDK) API 使用錯誤碼或 HRESULT 而非例外狀況處理來傳回錯誤結果,因此在遊戲程式碼基底中採用 C++ 例外狀況處理的程度完全由您決定。例外狀況不應用於流程控制,因此一般而言最佳用途是「快速失敗」情境,這可以簡化偵錯與撰寫程式碼。標準 C++ 程式庫的大部分內容都假設已啟用例外狀況處理以進行正確的錯誤處理。 不建議明確停用例外狀況處理,因為這會對當機後分析產生負面影響,且不會改善程式碼產生。我們不建議使用 /EHa,因為這可能會妨礙最佳化工具。
運算子 new 在配置失敗時一律會擲回 C++ 例外狀況。如果您想使用不擲回例外狀況的 new 版本,必須使用 new (std::nothrow)。如需詳細資訊,請參閱 std::nothrow (cppreference.com)。
C++ 提供許多機制來撰寫「例外狀況安全」的程式碼,無論是否明確使用例外狀況處理都能正常運作。例如 std::unique_ptr、std::shared_ptr 與 std::lock_guard。使用 Microsoft::WRL::ComPtr 等 COM 智慧指標自動處理 COM 參考計數,是「例外狀況安全」的,也較不容易出錯。一般而言,您應該優先使用資源取得即初始化 (RAII) 程式碼撰寫模式。
根據預設,使用 VS 2019 建置的 x64 原生程式碼會使用改良的例外狀況處理常式實作 ( __CxxFrameHandler4、__GSHandlerCheck_EH4)。因此,使用 VS 2019 建置的靜態程式庫與 VS 2017 C/C++ Runtime 不相容。VS 2017 建置的靜態程式庫則與 VS 2019 相容。
如需詳細資訊,請參閱下列內容:

執行階段程式庫 (/MD、/MDd)

建議的選擇是使用 Visual C/C++ Runtime 的多執行緒 DLL 版本。這可將程式碼膨脹降至最低、避免 DLL 之間互動的潛在問題、簡化服務,而且是所有 Microsoft 平台的建議選項。 對於 XBOX 上的 Microsoft Game Development Kit (GDK),這表示要連結至 ucrt.lib 或 ucrtd.lib。
技術上,您可以使用 libucrt.lib 或 libucrtd.lib 透過 /MT、/MTd 進行靜態 CRT 連結。GDK 不包含與靜態 CRT 相容的延伸程式庫,因此對此情境的支援有限。

呼叫慣例 (/Gd、/Gv)

x64 的原生程式碼產生使用簡單且標準的 __fastcall 呼叫慣例,可在暫存器中傳遞前四個參數。
  • 如果第一個參數是整數或指標對等項目,會在 RCX 中傳遞。如果是 float 或 double,會在 XMM0L 中傳遞。否則,會透過堆疊傳遞。
  • 如果第二個參數是整數或指標對等項目,會在 RDX 中傳遞。如果是 float 或 double,會在 XMM1L 中傳遞。否則,會透過堆疊傳遞。
  • 如果第三個參數是整數或指標對等項目,會在 R8 中傳遞。如果是 float 或 double,會在 XMM2L 中傳遞。否則,會透過堆疊傳遞。
  • 如果第四個參數是整數或指標對等項目,會在 R9 中傳遞。如果是 float 或 double,會在 XMM3L 中傳遞。否則,會透過堆疊傳遞。
  • 所有其他參數都會透過堆疊傳遞。
  • 可容納於 64 位元內的傳回值會在 RAX 中傳回。XMM0 用於傳回 float、double、__m128、__m128i 與 __m128d 值。否則,呼叫端會在 RCX 中以第 0 個引數傳入記憶體指標,且 RAX 必須以相同的指標傳回。
這些要點表示較短的函式簽章效能較佳,而傳遞物件的指標 (或參考) 比以值傳遞更快。呼叫慣例會自動以參考方式傳遞大於 8 位元組的物件。 在 __fastcall 配置中,SIMD 值絕不會在暫存器中傳遞。
對於 x64 原生程式碼,__cdecl、__stdcall 與 __thiscall 都是 __fastcall 的別名。
如需詳細資訊,請參閱 x64 呼叫慣例 (Microsoft Docs)。

向量呼叫

Visual Studio 支援一種稱為 __vectorcall 的選用呼叫慣例,用於 x64 原生程式碼產生。
  • 如果第一個參數是整數或指標對等項目,會在 RCX 中傳遞。如果是 float、double、__m128、__m128i 或 __m128d,參數會在 XMM0 中傳遞。如果是 __m256、__m256i 或 __m256d,會在 YMM0 中傳遞。否則,第一個參數會透過堆疊傳遞。
  • 如果第二個參數是整數或指標對等項目,會在 RDX 中傳遞。如果是 float、double、__m128、__m128i、__m128d、__m256、__m256i 或 __m256d,參數會在 XMM1/YMM1 中傳遞。否則,第二個參數會透過堆疊傳遞。
  • 如果第三個參數是整數或指標對等項目,會在 R8 中傳遞。如果是 float、double、__m128、__m128i、__m128d、__m256、__m256i 或 __m256d,參數會在 XMM2/YMM2 中傳遞。否則,第三個參數會透過堆疊傳遞。
  • 如果第四個參數是整數或指標對等項目,會在 R9 中傳遞。如果是 float、double、__m128、__m128i、__m128d、__m256、__m256i 或 __m256d,參數會在 XMM3/YMM3 中傳遞。否則,第四個參數會透過堆疊傳遞。
  • 如果第五個參數是 float、double、__m128、__m128i、__m128d、__m256、__m256i 或 __m256d,參數會在 XMM4/YMM4 中傳遞。否則,第五個參數會透過堆疊傳遞。
  • 如果第六個參數是 float、double、__m128、__m128i、__m128d、__m256、__m256i 或 __m256d,參數會在 XMM5/YMM5 中傳遞。否則,第六個參數會透過堆疊傳遞。
  • 所有其他參數都會透過堆疊傳遞。
  • 可容納於 64 位元內的傳回值會在 RAX 中傳回。XMM0 用於傳回 float、double、__m128、__m128i 與 __m128d 值。YMM0 用於傳回 __m256、__m256i 或 __m256d 值。否則,呼叫端會在 RCX 中以第 0 個引數傳入記憶體指標,且 RAX 必須以相同的指標傳回。
__vectorcall 慣例也可以處理同質向量彙總 (HVA) 類型,這種類型由一或多個相同種類的向量或浮點類型組成,最多四個成員 (也就是說,struct * { __m128 v[4]; } 是 HVA)。 作為以值傳遞的參數,如果在配置其他參數之後 XMM0/YMM0 - XMM5/YMM5 中有足夠的空間,HVA 就會在暫存器中傳遞。作為傳回值,HVA 會透過 XMM0/YMM0 - XMM3/YMM3 傳回。
__vectorcall 不支援 vararg 函式或 C++ 建構函式。
如需詳細資訊,請參閱下列內容:

全程式最佳化 (/GL、/Gw、/LTCG)

傳統的編譯器最佳化技術可以最佳化函式與模組,而全程式最佳化 (也稱為連結時間程式碼產生 (LTCG)) 則會跨模組執行最佳化。這包括透過更了解副作用來改善暫存器配置與排程、程序間的常數/範圍傳播、部分內嵌,以及在可能時對物件上的函式呼叫進行去虛擬化。
LTCG 也可以在累加模式中使用,以便在開發反覆運算時獲得程式碼效能好處。如需詳細資訊,請參閱 Speeding up the Incremental Developer Build Scenario (C++ Team Blog)。
對於發行預先建置之靜態 C++ 程式庫的中介軟體廠商,啟用 WPO 會將程式庫綁定至特定版本的編譯器工具組。在此情境中,您應該發行不含 WPO 的程式庫。此建議不適用於 DLL 或從原始碼建置的程式碼。
如需詳細資訊,請參閱 /GL (全程式最佳化) (Microsoft Docs)。
Visual Studio 2022 (17.5) 新增了與 /Gw 相關的新一致性參數 /Zc:checkGwOdr。請參閱此部落格文章。

分析導引最佳化

分析導引最佳化 (PGO) 將 LTCG 流程更進一步,由應用程式先前執行時收集的效能追蹤來控制全程式最佳化。這可提升現有最佳化的品質,以及函式配置、區塊配置與程式碼分離的最佳化,以改善工作集與分支預測。 如需詳細資訊,請參閱分析導引最佳化 (Microsoft Docs)。

/OPT:REF,ICF 連結器參數

這些參數會在連結至最終可執行檔時,消除各個目的模組中的多餘內容。一般而言,偵錯組建會停用這些參數,但發行組建應該要有這些參數。
為了獲得最佳結果,請務必使用 /Gy (啟用函式層級連結) 選項進行編譯。

/GS 編譯器參數

我們建議在所有程式碼的發行組態中使用緩衝區檢查。對於特定緩衝區不受安全性威脅、但效能似乎受到檢查影響的情況,請在函式上使用 __declspec(safebuffers),而不是全域停用 /GS。對於風險較高的程式碼,請使用 #pragma strict_gs_check(on)。 如需詳細資訊,請參閱 /GS (緩衝區安全性檢查) (Microsoft Docs)。

/homeparams 編譯器參數

在最佳化組建中使用此參數,可大幅提升偵錯應用程式發行組建的能力。如果用於正式組建,可以簡化分析與偵錯當機傾印的流程。這會增加少量在堆疊上儲存其他參數的負擔。在大多數情況下,這不會對效能造成明顯影響。 如需詳細資訊,請參閱 /homeparams (將暫存器參數複製到堆疊) (Microsoft Docs)。

/Zc:inline 編譯器參數

此參數會套用更嚴格的 C++11 內嵌函式宣告規則,要求所有內嵌函式的主體都必須存在於與其宣告及使用位置相同的編譯單位中。使用此旗標可以改善建置時間,並可大幅縮減 .obj 檔案的大小。如果您的內嵌函式不符合 C++11,則會在連結時收到 LNK2019 錯誤。使用 MSBuild 建置時,此參數預設為開啟,但使用命令列、CMake 等建置時必須明確新增。 如需詳細資訊,請參閱 /Zc:inline (移除未參考的 COMDAT) (Microsoft Docs)。

/Zc:throwingNew 編譯器參數

C++ 標準與標準 C++ 程式庫範本要求運算子 new 在配置失敗時擲回例外狀況,而不是傳回 nullptr——您可以搭配 new 使用 std::nothrow 來強制採用傳回 nullptr 的行為。Visual C++ 編譯器長久以來會在每次呼叫 new 之後產生 null 檢查,而在有例外狀況處理的情況下這是不必要的。使用此參數即可消除額外的檢查。 如需詳細資訊,請參閱下列內容:

/Zc:__cplusplus 編譯器參數

基於歷史因素,Visual C++ 中的 __cplusplus 巨集長久以來都傳回 “199711”。從 Visual Studio 2017 (15.7 更新) 開始,這個新參數會讓 Visual C++ 編譯器傳回正確的標準值。未來版本的編譯器預設會這麼做,因此值得儘早開啟此參數,以解決任何遺留的一致性問題。 如需詳細資訊,請參閱下列內容:

/volatile:iso 編譯器參數

關鍵字 volatile 有許多 Microsoft 特有的延伸行為,這些行為並非真正可攜,即使在不同世代的 Visual C++ 之間也是如此。您應該考慮開啟此參數,然後確保程式碼中沒有誤用 volatile。 如需詳細資訊,請參閱 /volatile (volatile 關鍵字解譯) (Microsoft Docs)。

/permissive- 編譯器參數

Visual Studio 2017 引進了新的標準一致性參數,以取代過時的 /Za 參數。此參數會使編譯器在使用可能於移植至其他編譯器時造成問題的 Microsoft 特有延伸行為時,發出錯誤與警告。使用 /permissive- 也可以改善編譯時間。 如需詳細資訊,請參閱下列內容:
從 Visual Studio 2017 (15.3 更新) 開始,使用 /permissive- 也會啟用兩階段名稱查閱。部分 C++ 範本程式碼在適當的標準強制下無法編譯,因此您可以使用 /Zc:twoPhase- 選擇性地只停用該部分,而不是完全停用 /permissive-。如需詳細資訊,請參閱下列內容:
與一致性強制相關的其他參數包括 /Zc:lambda 與 /Zc:templateScope。

/Zc:preprocessor 編譯器參數

Visual Studio 2019 (16.6) 包含一個新參數,可啟用符合 C99 的前置處理器。此參數預設為關閉,但如果您在意程式碼的可攜性,應考慮啟用它。請參閱 Announcing full support for a C/C++ conformant preprocessor in MSVC。

/ZH:SHA_256 編譯器參數

偵錯符號傳統上使用 MD5 雜湊。為了改善供應鏈安全性,建議改用 SHA-256。請注意,Visual Studio 2022 預設為 /ZH:SHA_256。
clang/LLVM 自 v16 起支援此參數。

/NXCOMPAT 與 /SAFESEH 連結器參數

使用 x64 原生目標時,這兩個參數是隱含的。XBOX 遊戲需要不可執行 (NX) 保護,因此您不能使用 /NXCOMPAT:NO。

/DYNAMICBASE 連結器參數

此參數可啟用位址空間配置隨機化 (ASLR),且預設為開啟。請注意,XBOX 遊戲需要此功能,因此您不能使用 /DYNAMICBASE:NO。 對於 Visual Studio 2019 (16.8) 或更新版本,由於連結器的效能大幅提升,我們不再建議使用 /Debug:FASTLINK。 對於本機組建,啟用此連結器參數可以大幅改善建置反覆運算時間。
請記住,使用 /Debug:FASTLINK 時,專案的主要 pdb 只包含指向分散在整個組建中之 pdb 檔案的連結。如果您想要分享或儲存 /Debug:FASTLINK 組建的符號,可以使用 mspdbcmf.exe 命令列工具產生完整的 pdb 檔案。如需詳細資訊,請參閱下列內容:

程式庫

對於 Gaming.Xbox.XboxOne.x64 與 Gaming.Xbox.Scarlett.x64 平台,連結 xgameplatform.lib 很重要。這是一個「傘形」程式庫,包含主機上支援的所有 Win32 API。請勿連結 kernel32.lib、onecore.lib、onecoreuap.lib 或 WindowsApps.lib。不建議混用傘形程式庫,這可能會導致處理序啟動失敗。 如需「傘形」程式庫的詳細資訊,請參閱 Microsoft Docs。

/NODEFAULTLIB:library 連結器參數

我們建議搭配一份特定的常見程式庫名稱清單使用 /NODEFAULTLIB 連結器參數,以確保在連結時不會透過 #pragma comment(lib,) 使用不受支援的程式庫。
如果某個程式庫被明確列為連結輸入,即使它被列為 /NODEFAULTLIB 程式庫,仍會被使用。此參數只會忽略隱含參考。

Visual C++ Runtime 程式庫

Visual Studio 開發人員命令提示字元 會定義尋找這些路徑所需的環境變數。 Gaming.Xbox.*.x64 用於尋找 Visual C++ Runtime 匯入程式庫的正確 /LIBPATH 為 %VCToolsInstallDir%lib\onecore\x64。

動態連結程式庫 (DLL)

Gaming.Xbox.*.x64 的 Game OS 不包含 Visual C++ Runtime DLL 程式庫。這些程式庫必須包含在遊戲配置中,遊戲才能啟動。
  • 對於 Release,您需要 %VCToolsRedistDir%onecore\x64\Microsoft.VC14?.CRT 的內容。如果同一個配置中同時有 Debug 與 Release 二進位檔,則您需要在所有配置中包含這些檔案。
  • 對於 Debug,您需要 %VCToolsRedistDir%onecore\debug_nonredist\x64\Microsoft.VC14?.DebugCRT 的內容。
  • 對於 Debug,您還需要偵錯版本的 ucrtbased.dll,它位於 Windows SDK 中:%WindowsSdkVerBinPath%x64\ucrt。Release 版本的 ucrtbase.dll 包含在 Game OS 中。
如果您使用 OpenMP,還需要 Microsoft.VC14?.OpenMP 和/或 Microsoft.VC14?.DebugOpenMP 的內容

另請參閱

CMakeExample 範例
最後修改於 2026年10月8日