现代 C++ 实战(02):C++ 版本演进一览
上一篇我们搞定了 CMake 构建。但在写代码之前,还有一个「地图」问题:C++ 到底演进了哪些版本?每个版本加了什么? 如果你还在用 C++98 的思维读 C++20 的代码,很容易觉得「语法怎么又变了」。
这一篇不深入任何单一特性,而是把 C++03 → C++26 的演进脉络梳理清楚,并带你跑一遍 version_features demo——后面 25 篇特性文章,都可以在这张地图上找到位置。
这是「现代 C++ 实战」系列的第 2 篇。对应 demo:
ref/cpp_demo/basics/version_features/。建议先读 第 01 篇:CMake 与现代构建。
一、C++ 标准时间线
C++ 不像 Python 那样每年一个大版本,而是 3~5 年发布一次国际标准(由 ISO 委员会制定)。对开发者来说,真正重要的是:编译器支持到了哪个 -std=。
| 标准 | 发布年份 | __cplusplus 宏 |
常用编译 flag | 定位 |
|---|---|---|---|---|
| C++98 / C++03 | 1998 / 2003 | 199711L | -std=c++03 |
经典 C++,STL 定型 |
| C++11 | 2011 | 201103L | -std=c++11 |
现代 C++ 起点 |
| C++14 | 2014 | 201402L | -std=c++14 |
C++11 的小修小补 |
| C++17 | 2017 | 201703L | -std=c++17 |
实用工具大爆发 |
| C++20 | 2020 | 202002L | -std=c++20 |
语言级现代化 |
| C++23 | 2023 | 202302L | -std=c++23 |
实用特性补齐 |
| C++26 | 2026 | 202603L | -std=c++26 |
反射、契约、执行框架 |
几个直觉:
- C++03 到 C++11 隔了 13 年,变动最大——很多人说的「现代 C++」就是从 C++11 算起。
- C++14 / C++17 是「好用」版本:不颠覆思维,但日常编码效率明显提升。
- C++20 是「换引擎」版本:Concepts、Ranges、协程、Modules 等进入标准。
- C++23 是「补账」版本:expected、print、deducing this 等前几版欠的实用特性陆续落地。
- C++26 是「2026 新定稿」版本(ISO 2026 年 3 月完成技术定稿):编译期反射、契约(Contracts)、
std::execution异步框架、pack indexing 等进入标准。 - 本系列 demo 标注了所需标准(C++11~C++26),CMake 里用
CMAKE_CXX_STANDARD或set_target_properties指定即可(见第 01 篇)。
二、C++11:现代 C++ 的起点
C++11 之前,写 C++ 像在开手动挡:内存自己管、线程自己封装、泛型报错看不懂。C++11 一次性补上了现代语言的核心拼图:
| 类别 | 代表特性 | 本系列对应篇 |
|---|---|---|
| 类型系统 | auto、decltype、enum class |
第 06 篇 Lambda |
| 内存管理 | unique_ptr / shared_ptr、右值引用、移动语义 |
第 03–05 篇 |
| 泛型与函数式 | Lambda、可变参数模板、std::function |
第 06 篇 |
| 并发 | std::thread、mutex、future |
第 12 篇 |
| 容器与工具 | unordered_map、array、tuple、chrono |
各 demo 中广泛使用 |
version_features/11.cpp 里几乎是一份 C++11 特性清单:decltype、智能指针、右值引用、std::thread、完美转发雏形等。运行它:
1 | cd ref/cpp_demo/basics/version_features |
文件开头有一句:
1 | static_assert(__cplusplus == 201103, ""); |
这行代码的含义是:这个翻译单元必须按 C++11 标准编译,否则直接报错——比运行时才发现问题更早、更干净。
三、C++14 / C++17:实用增强
C++14:让 C++11 更好用
C++14 改动不大,但几个特性非常「省心」:
| 特性 | 作用 | demo 中的例子 |
|---|---|---|
| 返回值类型推导 | auto func() 自动推导返回类型 |
deduced_return_type() |
| 泛型 Lambda | [](auto x){} 参数类型自动推导 |
14.cpp 中的 lambda 示例 |
make_unique |
与 make_shared 对称,异常更安全 |
智能指针 demo |
| 二进制字面量 | 0b1010 |
位操作更清晰 |
std::exchange |
原子地交换并赋值 | 移动语义辅助 |
运行 C++14 demo:
1 | ./build.sh --run-args './build/demo_14' |
C++17:日常开发的工具箱
C++17 是很多人日常项目的「甜点版本」——编译器支持广泛,特性又足够新:
| 特性 | 一句话 | 本系列 |
|---|---|---|
| 结构化绑定 | auto [k, v] = pair |
第 07 篇 |
if constexpr |
编译期分支,替代 SFINAE 技巧 | 第 07 / 11 篇 |
std::optional / variant / any |
类型安全的「可能有值」 | 第 07–08 篇 |
std::filesystem |
跨平台文件路径操作 | 第 07 篇 |
| 类模板参数推导 (CTAD) | pair p(1, 2.3) 不用写模板参数 |
17.cpp |
| 折叠表达式 | (args + ...) 可变参数求和 |
第 07 篇 |
| 并行算法 | std::execution::par |
第 07 篇 |
17.cpp 里 CTAD 的写法很直观:
1 | constexpr pair deducted_pair(1, 2.3); // 推导为 pair<int, double> |
运行:
1 | ./build.sh --run-args './build/demo_17' |
四、C++20:语言级现代化
C++20 不是「多加几个函数」,而是改写了写 C++ 的方式:
| 特性 | 解决什么问题 | 本系列 |
|---|---|---|
| Concepts | 模板报错像天书 → 约束模板参数 | 第 11 篇 |
| Ranges | 算法 + 迭代器组合冗长 → 管道式链式调用 | 第 10 篇 |
| Coroutines | 异步回调地狱 → co_await 协作式多任务 |
第 27 篇 |
| Modules | 头文件编译慢 → 模块导入(仍在普及中) | — |
std::format |
printf / iostream 不安全 → 类型安全格式化 |
第 09 篇 |
三路比较 <=> |
手写 6 个比较运算符 → 自动生成 | 20.cpp |
| 指定初始化器 | 指定 .x = 1 初始化 struct 成员 |
20.cpp |
20.cpp 中的三路比较:
1 | static_assert(1 <=> 2 < 0); // less |
C++20 对编译器版本要求更高。macOS 上建议 Apple Clang 14+ 或 GCC 10+;若 demo_20 编译失败,先查编译器版本,再对照 cppreference 编译器支持表。
1 | ./build.sh --run-args './build/demo_20' |
五、C++23:实用特性补齐
C++23 于 2023 年发布,GCC 14+ / Clang 18+ 已能完整支持大部分特性。几个最值得日常使用的:
| 特性 | 说明 | 本系列 |
|---|---|---|
std::expected |
类似 Rust 的 Result<T, E>,错误处理更明确 |
第 08 / 17 篇 |
std::print / println |
比 format + cout 更简洁的输出 |
第 17 篇 |
deducing this |
成员函数自动推导 this 类型,简化 CRTP |
进阶 |
std::generator |
协程生成器,简化迭代器实现 | 第 27 篇 |
std::mdspan |
多维数组视图,科学计算友好 | — |
if consteval |
区分编译期与运行时分支 | 第 09 篇 |
0uz 字面量 |
size_t 后缀,消除与 int 比较的符号警告 |
23.cpp |
23.cpp 中的 std::expected 用法:
1 | std::expected<int, ParseError> parse_int(const std::string& s) { |
运行 C++23 demo:
1 | ./build.sh --run-args './build/demo_23' |
本系列第 17 篇会专门跑 cpp23_features demo,那里有更完整的 expected / deducing this 演示。
六、C++26:2026 定稿的新标准
2026 年 3 月,ISO C++ 委员会完成了 C++26 的技术定稿(ISO/IEC 14882:2026)。这是继 C++23 之后最新一版国际标准,几个标志性变化:
| 特性 | 说明 | 编译器支持 |
|---|---|---|
| 编译期反射(Reflection) | ^^ 运算符在编译期获取类型元信息 |
GCC 16+ 实验性 |
| 契约(Contracts) | pre / post / contract_assert 替代 C 风格 assert |
GCC 16+ 部分 |
std::execution |
Sender/Receiver 异步执行框架 | 逐步落地 |
| Pack indexing | args...[0] 直接索引参数包 |
Clang 19+ / GCC 15+ |
| 内存安全改进 | 读取未初始化局部变量不再 UB;标准库加固 | 重编译即生效 |
<inplace_vector> |
固定容量、栈上可扩容向量 | 逐步落地 |
26.cpp 中的 pack indexing(C++26 核心语言特性之一):
1 | template <typename... Ts> |
运行 C++26 demo:
1 | ./build.sh --run-args './build/demo_26' |
注意:C++26 刚定稿,各编译器支持仍在快速推进中。Apple Clang 21 已支持 pack indexing 和 std::println,但反射和契约可能还需等待后续版本。新项目不必立刻切 C++26,但应了解方向——本系列第 17 篇及后续会逐步覆盖。
七、编译器怎么选?
不同编译器、不同版本,对标准的支持进度不同。日常开发可以记这张简表:
| 编译器 | 推荐最低版本 | C++17 | C++20 | C++23 | C++26 | 常见场景 |
|---|---|---|---|---|---|---|
| GCC | 14+ | ✅ 完整 | ✅ 完整 | ✅ 大部分 | 部分 | Linux 服务器、Docker |
| Clang | 18+ | ✅ 完整 | ✅ 完整 | ✅ 大部分 | 部分 | macOS、clangd |
| Apple Clang | 16+ (Xcode 16) | ✅ | ✅ | ✅ 大部分 | 少量 | macOS 本地开发 |
| MSVC | VS 2022 17.8+ | ✅ | ✅ | 大部分 | 少量 | Windows |
实用建议:
- 新项目默认 C++17,除非明确需要 C++20 特性(Concepts、Ranges、协程等)。
- CMake 里写死标准并开启 REQUIRED(第 01 篇),避免静默降级。
- CI 与本地编译器尽量一致——Docker 环境就是为了这个(第 00 篇)。
- 查某个特性是否可用:cppreference 的 Compiler Support 表,或代码里
#if __cpp_xxx宏(demo 中大量使用)。
八、demo 导览:version_features
ref/cpp_demo/basics/version_features/ 把各版本特性拆成独立可执行文件:
| 可执行文件 | 标准 | 源文件 | 主要内容 |
|---|---|---|---|
demo_03 |
C++11* | 03.cpp |
关联容器、RAII 雏形、经典 STL |
demo_11 |
C++11 | 11.cpp |
auto、智能指针、线程、Lambda |
demo_14 |
C++14 | 14.cpp |
返回值推导、泛型 Lambda |
demo_17 |
C++17 | 17.cpp |
CTAD、optional、variant、结构化绑定 |
demo_20 |
C++20 | 20.cpp |
<=>、指定初始化、协程、bit_cast |
demo_23 |
C++23 | 23.cpp |
expected、println、deducing this、if consteval |
demo_26 |
C++26 | 26.cpp |
pack indexing、mdspan 多维下标 |
test_20 |
C++20 | test_20.cpp |
C++20 特性补充测试 |
* 注:demo_03 的 CMake 目标实际设为 C++11 编译,但内容展示的是 C++03 时代的惯用法与容器。
CMake 为每个 target 单独指定标准——这正是多版本 demo 共存的关键:
1 | add_executable(demo_11 11.cpp) |
一键运行全部
1 | cd ref/cpp_demo/basics/version_features |
build.sh --run 会依次编译并执行 build/ 下所有可执行文件。首次编译若 C++20 target 报错,优先检查编译器版本。
建议阅读顺序
demo_03— 感受「没有智能指针、没有 auto」时代怎么写demo_11— 现代 C++ 的「大爆炸」demo_14→demo_17— 逐步变好用demo_20— 语言级现代化demo_23→demo_26— 最新标准实用特性与前沿方向
九、如何用到本系列后续文章?
把本篇当作目录页,后面每一篇深入一个特性:
| 篇号 | 主题 | 版本 | demo |
|---|---|---|---|
| 03 | 移动语义 | C++11 | right_ref_demo/ |
| 04–05 | 智能指针 | C++11 | smart_pointers/ |
| 06 | Lambda | C++11/14/20 | lambda_demo/ |
| 07 | C++17 工具箱 | C++17 | any_demo 等 |
| 09–11 | format / Ranges / Concepts | C++20 | 各 demo |
| 12–14 | 并发 | C++11/20 | concurrency/ |
| 17 | C++23 | C++23 | cpp23_features/ |
| — | C++26 预览 | C++26 | version_features/26.cpp |
遇到编译错误时,先问自己两个问题:
- 这个 demo 需要哪个
-std=c++XX? - 我的编译器版本够不够?
十、小结
本篇梳理了 C++ 标准从 03 到 26 的演进路线:
- C++11 是现代 C++ 的分水岭——智能指针、移动语义、Lambda、线程
- C++14/17 让日常编码更高效——CTAD、optional、filesystem、并行算法
- C++20 带来 Concepts、Ranges、协程、format 等语言级变革
- C++23 补齐 expected、print、deducing this 等实用特性
- C++26(2026 定稿)引入反射、契约、pack indexing、
std::execution等 version_featuresdemo 按版本拆分(03 → 26),可逐个编译运行
现代 C++ 实战系列第 2 篇完。下一篇我们深入 移动语义与右值引用——
std::move到底在干什么,为什么它能大幅提升性能。
系列导航
| 篇号 | 标题 | 状态 |
|---|---|---|
| 00 | 环境搭建与项目导览 | ✅ |
| 01 | CMake 与现代构建 | ✅ |
| 02 | C++ 版本演进一览(本篇) | ✅ |
| 03 | 移动语义与右值引用 | 下一篇 |
完整大纲见工作区 docs/CPP_SERIES_OUTLINE.md。









