MSVC
Microsoft Visual C++ — Windows-native compiler required for COM, WinRT, UWP, and Xbox development. Ships with Visual Studio and Build Tools.
TL;DR
MSVC is the Windows-native C++ compiler. Required for COM, WinRT, UWP, and Xbox development. Use /W4 /WX for warnings, /O2 for release optimization, and /std:c++20 or /std:c++latest for modern C++. Available free via Visual Studio Community or standalone Build Tools.
REM Command line (Developer Command Prompt)
cl /std:c++20 /O2 /W4 /EHsc /Fe:myapp.exe main.cpp
REM With sanitizers (VS 2019 16.9+)
cl /std:c++20 /O1 /fsanitize=address /Zi /Fe:myapp.exe main.cppStandards support
| Standard | Flag |
|---|---|
| C++14 | /std:c++14 |
| C++17 | /std:c++17 |
| C++20 | /std:c++20 |
| C++23 (partial) | /std:c++latest |
Use /std:c++20 for production; /std:c++latest to track C++23/26 features in development.
Essential flags
Warning flags
/W0 REM No warnings
/W1 REM Severe warnings only
/W2 REM Significant warnings (default)
/W3 REM Production quality warnings
/W4 REM Informational warnings (recommended)
/Wall REM All warnings including rarely-used ones (noisy)
/WX REM Treat warnings as errorsRecommended: /W4 /WX for new projects.
Optimization flags
/Od REM No optimization (debug)
/O1 REM Minimize size
/O2 REM Maximize speed (release default)
/Ox REM Full optimization
/GL REM Whole-program optimization (link-time)
/LTCG REM Link-time code generation (pair with /GL)Exception handling
/EHsc REM Standard C++ exception handling (use this)
/EHa REM Also catches SEH (structured exceptions)
/EHs REM No async exceptionsAlways specify /EHsc explicitly. Without it, destructors may not run during stack unwinding.
Debug information
/Zi REM PDB debug info (separate .pdb file)
/ZI REM PDB with Edit-and-Continue support (dev only)
/Zd REM Line numbers onlyRuntime library
/MD REM Dynamic CRT (release) — use in DLLs and shared libraries
/MDd REM Dynamic CRT (debug)
/MT REM Static CRT (release) — for standalone executables
/MTd REM Static CRT (debug)All components in a project must use the same runtime. Mixing /MD and /MT causes linker errors or runtime crashes.
Sanitizers (VS 2019+)
REM AddressSanitizer
cl /fsanitize=address /Zi /Od main.cpp
REM In CMake
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address")MSVC ASan requires VS 2019 16.9+ and works on x64 only.
CMake integration
cmake_minimum_required(VERSION 3.20)
project(myapp CXX)
set(CMAKE_CXX_STANDARD 20)
add_executable(myapp main.cpp)
target_compile_options(myapp PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:/W4 /WX /EHsc>
)
# Enable WPO/LTCG for Release
set_target_properties(myapp PROPERTIES
INTERPROCEDURAL_OPTIMIZATION_RELEASE ON
)Clang-cl — Clang with MSVC ABI
clang-cl is a drop-in replacement that accepts MSVC flags but uses Clang's frontend:
clang-cl /std:c++20 /O2 /W4 /EHsc /Fe:myapp.exe main.cppUse clang-cl when you want:
- Clang's better error messages on Windows
- clang-tidy integration with MSVC ABI compatibility
- The same binary ABI as MSVC (COM, WinRT compatible)
Precompiled headers
// stdafx.h (or pch.h)
#pragma once
#include <vector>
#include <string>
#include <memory>
// ... all stable headersREM Create PCH
cl /Yc"pch.h" /FpMyPCH.pch pch.cpp
REM Use PCH
cl /Yu"pch.h" /FpMyPCH.pch main.cppIn CMake:
target_precompile_headers(myapp PRIVATE pch.h)Common MSVC-specific extensions
// __declspec — Windows-specific attributes
__declspec(dllexport) void myFunc(); // Export from DLL
__declspec(dllimport) void myFunc(); // Import from DLL
__declspec(noinline) void slow(); // Prevent inlining
__declspec(align(16)) float data[4]; // Alignment
// Structured Exception Handling (Windows SEH)
__try {
// code that might throw SEH
} __except(EXCEPTION_EXECUTE_HANDLER) {
// handle
}
// Prefer standard [[nodiscard]], [[likely]] etc. over MSVC extensionsNotable MSVC quirks
/permissive- — enables strict conformance mode. Add this to catch non-portable code:
cl /std:c++20 /permissive- main.cppTwo-phase lookup: MSVC historically had broken two-phase name lookup. /permissive- fixes this. Always use it in new projects.
__int64 vs long long: On MSVC, long is 32-bit even on 64-bit Windows (LLP64 model). Use int64_t / uint64_t from <cstdint> for portable 64-bit integers.
min/max macros: Windows headers define min/max as macros. Use #define NOMINMAX before including <windows.h> or use (std::min)() with parentheses.
#define NOMINMAX
#include <windows.h>
#include <algorithm>
auto x = std::min(a, b); // Fine