modern-cpp

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Modern C++

现代C++

Guide for writing modern C++ using C++20, C++23, and C++26 idioms. Focuses on patterns that eliminate vulnerability classes and reduce boilerplate, with a security emphasis from Trail of Bits.
本指南介绍如何使用C++20、C++23和C++26的编程范式编写现代C++代码。重点关注可消除漏洞类型、减少冗余代码的模式,由Trail of Bits提供安全方面的专业支持。

When to Use This Skill

适用场景

  • Writing new C++ functions, classes, or libraries
  • Modernizing existing C++ code (pre-C++20 patterns)
  • Choosing between legacy and modern approaches
  • Working on security-critical or safety-sensitive C++
  • Reviewing C++ code for modern idiom adoption
  • 编写新的C++函数、类或库
  • 改造现有C++代码(C++20之前的模式)
  • 在遗留方案与现代方案之间做选择
  • 处理安全关键或安全敏感型C++代码
  • 审查C++代码的现代范式采用情况

When NOT to Use This Skill

不适用场景

  • User explicitly requires older standard: Respect constraints (embedded, legacy ABI)
  • Pure C code: This skill is C++-specific
  • Build system questions: CMake, Meson, Bazel configuration is out of scope
  • Non-C++ projects: Mixed codebases where C++ isn't primary
  • 用户明确要求使用旧标准:遵守约束(嵌入式系统、遗留ABI)
  • 纯C代码:本技能仅针对C++
  • 构建系统问题:CMake、Meson、Bazel配置不在范围内
  • 非C++主导项目:C++并非核心语言的混合代码库

Anti-Patterns to Avoid

需避免的反模式

AvoidUse InsteadWhy
new
/
delete
std::make_unique
,
std::make_shared
Eliminates leaks, double-free
Raw owning pointers
std::unique_ptr
,
std::shared_ptr
RAII ownership semantics
C arrays (
int arr[N]
)
std::array<int, N>
Bounds-aware, value semantics
Pointer + length params
std::span<T>
Non-owning, bounds-checkable
printf
/
sprintf
std::format
,
std::print
Type-safe, no buffer overflow
C-style casts
(int)x
static_cast<int>(x)
Explicit intent, auditable
#define
constants
constexpr
variables
Scoped, typed, debuggable
SFINAE /
enable_if
Concepts +
requires
Readable constraints and errors
Error codes + out params
std::expected<T, E>
Composable, type-safe errors
union
std::variant
Type-safe, no silent UB
Raw
mutex.lock()/unlock()
std::scoped_lock
Exception-safe, no deadlocks
std::thread
std::jthread
Auto-join, stop token support
assert()
macro
contract_assert
(C++26)
Visible to tooling, configurable
Manual CRTPDeducing
this
(C++23)
Simpler, no template boilerplate
Macro code generationReflection (C++26)Zero-overhead, composable
See anti-patterns.md for the full table (30+ patterns).
需避免的写法替代方案原因
new
/
delete
std::make_unique
,
std::make_shared
消除内存泄漏、重复释放问题
原始拥有指针
std::unique_ptr
,
std::shared_ptr
遵循RAII所有权语义
C数组 (
int arr[N]
)
std::array<int, N>
支持边界检查,具备值语义
指针+长度参数
std::span<T>
非所有权,可检查边界
printf
/
sprintf
std::format
,
std::print
类型安全,无缓冲区溢出风险
C风格强制转换
(int)x
static_cast<int>(x)
意图明确,易于审计
#define
常量
constexpr
变量
具备作用域、类型化,可调试
SFINAE /
enable_if
Concepts +
requires
约束和错误信息更易读
错误码+输出参数
std::expected<T, E>
可组合,类型安全的错误处理
union
std::variant
类型安全,无静默未定义行为
手动
mutex.lock()/unlock()
std::scoped_lock
异常安全,避免死锁
std::thread
std::jthread
自动join,支持停止令牌
assert()
contract_assert
(C++26)
工具可识别,可配置
手动CRTPDeducing
this
(C++23)
更简洁,无需模板冗余代码
宏代码生成Reflection (C++26)零开销,可组合
完整表格(30+种模式)请查看 anti-patterns.md

Decision Tree

决策树

What are you doing?
|
+-- Writing new C++ code?
|   +-- Use modern idioms by default (C++20/23)
|   +-- Choose the newest standard your compiler supports
|   +-- See Feature Tiers below
|
+-- Modernizing existing code?
|   +-- Start with Tier 1 (C++20/23) replacements
|   +-- Prioritize by security impact (memory > types > style)
|   +-- See anti-patterns.md for the migration table
|
+-- Security-critical code?
|   +-- Enable compiler hardening flags (see below)
|   +-- Enable hardened libc++ mode
|   +-- Run sanitizers in CI
|   +-- See safe-idioms.md and compiler-hardening.md
|
+-- Using C++26 features?
    +-- Reflection: YES, plan for it (GCC 16+)
    +-- Contracts: cautiously, for new API boundaries
    +-- std::execution: wait for ecosystem maturity
    +-- See cpp26-features.md
你正在做什么?
|
+-- 编写新C++代码?
|   +-- 默认使用现代范式(C++20/23)
|   +-- 选择编译器支持的最新标准
|   +-- 查看下方的特性层级
|
+-- 改造现有代码?
|   +-- 从第一层级(C++20/23)的替代方案开始
|   +-- 按安全影响优先级处理(内存 > 类型 > 风格)
|   +-- 查看anti-patterns.md中的迁移表格
|
+-- 处理安全关键型代码?
|   +-- 启用编译器加固标志(见下文)
|   +-- 启用强化版libc++模式
|   +-- 在CI中运行 sanitizers
|   +-- 查看safe-idioms.md和compiler-hardening.md
|
+-- 使用C++26特性?
    +-- Reflection:推荐使用(GCC 16+支持)
    +-- Contracts:谨慎使用,适用于新的API边界
    +-- std::execution:等待生态成熟后再使用
    +-- 查看cpp26-features.md

Feature Tiers

特性层级

Features are ranked by practical usability today, not by standard version.
特性按当前实际可用性排序,而非标准版本。

Tier 1: Use Today (C++20/23, solid compiler support)

第一层级:立即使用(C++20/23,编译器支持完善)

FeatureReplacesStandard
Concepts +
requires
SFINAE,
enable_if
C++20
Ranges + viewsRaw iterator loopsC++20
std::span<T>
Pointer + lengthC++20
std::format
sprintf
, iostream chains
C++20
Three-way comparison
<=>
Manual comparison operatorsC++20
std::jthread
std::thread
+ manual join
C++20
Designated initializersPositional struct initC++20
std::expected<T,E>
Error codes, exceptions at boundariesC++23
std::print
/
std::println
printf
,
std::cout <<
C++23
Deducing
this
CRTP, const/non-const duplicationC++23
std::flat_map
std::map
for read-heavy use
C++23
Monadic
std::optional
Nested if-checks on optionalsC++23
See cpp20-features.md and cpp23-features.md.
特性替代对象标准版本
Concepts +
requires
SFINAE,
enable_if
C++20
Ranges + views原始迭代器循环C++20
std::span<T>
指针+长度C++20
std::format
sprintf
, 流操作链
C++20
三路比较运算符
<=>
手动实现比较运算符C++20
std::jthread
std::thread
+ 手动join
C++20
指定初始化器结构体位置初始化C++20
std::expected<T,E>
错误码、边界处的异常C++23
std::print
/
std::println
printf
,
std::cout <<
C++23
Deducing
this
CRTP、const/non-const代码重复C++23
std::flat_map
读密集场景下的
std::map
C++23
单子式
std::optional
对optional的嵌套if检查C++23
详情请查看 cpp20-features.mdcpp23-features.md

Tier 2: Deploy Now (no standard bump needed)

第二层级:立即部署(无需升级标准版本)

These improve safety without changing your C++ standard version:
  • Compiler hardening flags
    -D_FORTIFY_SOURCE=3
    ,
    -fstack-protector-strong
    ,
    -ftrivial-auto-var-init=zero
  • Hardened libc++
    -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST
    for ~0.3% overhead bounds-checking
  • Sanitizers in CI — ASan + UBSan as minimum; TSan for concurrent code
  • Warning flags
    -Wall -Wextra -Wpedantic -Werror
See compiler-hardening.md.
这些特性可提升安全性,无需更改C++标准版本:
  • 编译器加固标志
    -D_FORTIFY_SOURCE=3
    ,
    -fstack-protector-strong
    ,
    -ftrivial-auto-var-init=zero
  • 强化版libc++
    -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST
    ,仅带来约0.3%的性能开销,同时提供边界检查
  • CI中的Sanitizers — 至少启用ASan + UBSan;并发代码启用TSan
  • 警告标志
    -Wall -Wextra -Wpedantic -Werror
详情请查看 compiler-hardening.md

Tier 3: Plan For (C++26, worth restructuring around)

第三层级:规划使用(C++26,值得重构适配)

Reflection is the single most transformative C++26 feature. It eliminates:
  • Serialization boilerplate (one generic function replaces per-struct
    to_json
    )
  • Code generators (protobuf codegen, Qt MOC)
  • Macro-based registration and enum-to-string hacks
GCC 16 (April 2026) has reflection merged. Plan new code to benefit from it.
Reflection是C++26中最具变革性的特性。它可消除:
  • 序列化冗余代码(一个通用函数替代每个结构体的
    to_json
  • 代码生成器(protobuf代码生成、Qt MOC)
  • 基于宏的注册和枚举转字符串的技巧
GCC 16(2026年4月)已合并Reflection特性。规划新代码时可考虑从中受益。

Tier 4: Watch (C++26, needs maturation)

第四层级:持续关注(C++26,需等待成熟)

  • Contracts (
    pre
    /
    post
    /
    contract_assert
    ) — Better than
    assert()
    , but no virtual function support and limited compiler support. Adopt cautiously for new API boundaries.
  • std::execution (senders/receivers) — Powerful async framework, but steep learning curve, no scheduler ships with it, and poor documentation. Wait for ecosystem maturity.
See cpp26-features.md.
  • Contracts (
    pre
    /
    post
    /
    contract_assert
    ) — 比
    assert()
    更优,但不支持虚函数,编译器支持有限。仅在新API边界处谨慎采用。
  • std::execution(发送者/接收者) — 强大的异步框架,但学习曲线陡峭,无内置调度器,文档不完善。等待生态成熟后再使用。
详情请查看 cpp26-features.md

Compiler Hardening Quick Reference

编译器加固快速参考

Essential Flags (GCC + Clang)

核心标志(GCC + Clang)

-Wall -Wextra -Wpedantic -Werror
-D_FORTIFY_SOURCE=3
-fstack-protector-strong
-fstack-clash-protection
-ftrivial-auto-var-init=zero
-fPIE -pie
-Wl,-z,relro,-z,now
-Wall -Wextra -Wpedantic -Werror
-D_FORTIFY_SOURCE=3
-fstack-protector-strong
-fstack-clash-protection
-ftrivial-auto-var-init=zero
-fPIE -pie
-Wl,-z,relro,-z,now

Clang-Specific

Clang专属标志

-Wunsafe-buffer-usage
-Wunsafe-buffer-usage

Hardened libc++ (Clang/libc++ only)

强化版libc++(仅Clang/libc++支持)

-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST
Google deployed this across Chrome and their server fleet: ~0.3% overhead, 1000+ bugs found, 30% reduction in production segfaults.
See compiler-hardening.md for the full guide.
-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST
谷歌已在Chrome及其服务器集群中部署该配置:仅约0.3%的性能开销,发现1000+漏洞,生产环境段错误减少30%。
完整指南请查看 compiler-hardening.md

Rationalizations to Reject

需拒绝的错误理由

RationalizationWhy It's Wrong
"It compiles without warnings"Warnings depend on which flags you enable. Add
-Wall -Wextra -Wpedantic
.
"ASan is too slow for production"Use GWP-ASan for sampling-based production detection (~0% overhead).
"We only use safe containers"Iterator invalidation and unchecked
optional
access are still exploitable.
"Smart pointers are slower"
std::unique_ptr
has zero overhead vs raw pointers. Measure before claiming.
"Our code doesn't have memory bugs"Google found 1000+ bugs when enabling hardened libc++. So did everyone else.
"C++26 features aren't available yet"C++20/23 features are. Hardening flags work on any standard. Start there.
"Modern C++ is harder to read"
std::expected
is more readable than checking error codes across 5 out-params.
错误理由错误原因
"代码编译无警告"警告取决于启用的标志。添加
-Wall -Wextra -Wpedantic
"ASan在生产环境中太慢"使用GWP-ASan进行基于采样的生产环境检测(约0%性能开销)。
"我们只使用安全容器"迭代器失效和未检查的
optional
访问仍可被利用。
"智能指针更慢"
std::unique_ptr
与原始指针相比零开销。先做性能测试再下结论。
"我们的代码没有内存漏洞"谷歌启用强化版libc++时发现了1000+漏洞,其他公司也是如此。
"C++26特性还不可用"C++20/23特性已可用。加固标志适用于所有标准版本。从这些开始。
"现代C++更难读"
std::expected
比检查5个输出参数的错误码更易读。

Best Practices Checklist

最佳实践检查清单

  • Use smart pointers for ownership, raw pointers only for non-owning observation
  • Prefer
    std::span
    over pointer + length for function parameters
  • Use
    std::expected
    for functions that can fail with typed errors
  • Constrain templates with concepts, not SFINAE
  • Enable compiler hardening flags and hardened libc++ in all builds
  • Run ASan + UBSan in CI; add TSan for concurrent code
  • Use
    constexpr
    /
    consteval
    where possible (UB-free by design)
  • Mark functions
    [[nodiscard]]
    when ignoring the return value is likely a bug
  • Prefer value semantics; use
    std::variant
    over
    union
    ,
    enum class
    over
    enum
  • Initialize all variables at declaration
  • 使用智能指针管理所有权,原始指针仅用于非所有权的观测
  • 函数参数优先使用
    std::span
    而非指针+长度
  • 可能失败的函数使用
    std::expected
    处理类型化错误
  • 用Concepts约束模板,而非SFINAE
  • 在所有构建中启用编译器加固标志和强化版libc++
  • 在CI中运行ASan + UBSan;并发代码添加TSan
  • 尽可能使用
    constexpr
    /
    consteval
    (设计上无未定义行为)
  • 当忽略返回值可能导致bug时,为函数标记
    [[nodiscard]]
  • 优先使用值语义;用
    std::variant
    替代
    union
    ,用
    enum class
    替代
    enum
  • 所有变量在声明时初始化

Read Next

后续阅读

  • anti-patterns.md — Full legacy-to-modern migration table (30+ patterns)
  • cpp20-features.md — Concepts, ranges, span, format, coroutines
  • cpp23-features.md — expected, print, deducing this, flat_map
  • cpp26-features.md — Reflection, contracts, memory safety improvements
  • compiler-hardening.md — Flags, sanitizers, hardened libc++
  • safe-idioms.md — Security patterns by vulnerability class
  • anti-patterns.md — 完整的遗留到现代模式迁移表格(30+种模式)
  • cpp20-features.md — Concepts、Ranges、Span、Format、协程
  • cpp23-features.md — Expected、Print、Deducing This、Flat_map
  • cpp26-features.md — Reflection、Contracts、内存安全改进
  • compiler-hardening.md — 标志、Sanitizers、强化版libc++
  • safe-idioms.md — 按漏洞类型分类的安全模式