自 C++11 起,C++ 经历了一场脱胎换骨的现代化变革。移动语义、Lambda、智能指针让 C++ 从"带类的 C"演变为一门表达能力媲美高层语言的系统级语言;C++20 的 Concepts、Ranges、Coroutines 三大特性更是将 C++ 推向了新的抽象高度;C++23 和即将到来的 C++26 则继续在并发、容器、类型系统等方向深耕。
本专题旨在逐一解剖这些关键特性——不讲"是什么"的表层,而是追问"为什么这样设计""编译器在背后做了什么""正确用法和致命陷阱分别在哪里"。
自 C++11 起,C++ 经历了一场脱胎换骨的现代化变革。移动语义、Lambda、智能指针让 C++ 从"带类的 C"演变为一门表达能力媲美高层语言的系统级语言;C++20 的 Concepts、Ranges、Coroutines 三大特性更是将 C++ 推向了新的抽象高度;C++23 和即将到来的 C++26 则继续在并发、容器、类型系统等方向深耕。
本专题旨在逐一解剖这些关键特性——不讲"是什么"的表层,而是追问"为什么这样设计""编译器在背后做了什么""正确用法和致命陷阱分别在哪里"。
在 C++98 时代,编译期计算几乎等同于模板元编程(TMP)——用递归模板 + 特化在类型系统里模拟图灵完备的计算。代码晦涩,编译慢,出错信息堪称灾难。C++11 引入了 constexpr,承诺让"正常 C++ 代码"在编译期运行。此后每一个标准版本都在放宽它的能力边界,到 C++20/23,你几乎可以在编译期做任何事。
本文梳理 constexpr 从 C++11 到 C++23 的演进历程,重点解释 if constexpr、consteval、constinit 三个极易混淆的概念,以及编译期容器的内存模型。
C++23 不是一个大爆炸式的标准版本——它更像是 C++20 骨架之上的肌肉和筋络。在处理"没有大语法引进"的版本时,真正改变日常编码体验的往往是那些看起来不起眼的新增类型和成员函数。
本文聚焦三个在工程实践中影响最大的 C++23 新增:std::expected(取代异常和输出参数的新范式)、std::spanstream(零拷贝字符串流)、以及 std::optional 的 monadic 扩展。
C++ 的 #include 模型已经用了四十多年。它的工作方式简单粗暴:预处理器把被包含文件的内容文本复制到 #include 的位置,然后编译器对着拼接后的翻译单元(translation unit)开始解析。
这个模型有三个根本性的缺陷:
.cpp 独立编译一次(N 个翻译单元 = N 次完全相同的前端处理)#define 影响它之后的所有 #include,不按作用域隔离C++20 Modules 正是为了解决这三个问题而诞生的。它把"编译中间结果"提升为一等公民,让编译器的前端工作从 O(N × headers) 降到 O(headers + N)。
C++98 以来的 STL 算法库一直有一个尴尬的体验:算法威力强大,但调用方式令人难受——std::sort(v.begin(), v.end()) 写了几十年。当你需要把"筛选、变换、去重、排序"组合起来时,每次中间操作都要分配新容器,或者把 begin/end 反复传递。
C++20 Ranges 彻底改变了这一局面。它把 STL 从"基于迭代器对"升级为"基于范围"的编程模型,并引入 views 管道——链式调用、懒惰求值、零拷贝中间结果。