校准基础认知¶
建立 C++11、C++14、C++17、C++20 的整体版本地图,先把边界理清。
目标:看到一个特性时,先能判断它属于哪个标准、解决哪类问题、在整体演进里处于哪一层,以及它主要在替代什么旧写法,而不是把 11、14、17、20 混成一团。
1 版本定位¶
-
C++11:现代 C++ 起点
建立类型推导、值语义、lambda、并发等现代基础设施。 -
C++14:对 C++11 的补强
让推导、泛型和 constexpr 更自然。 -
C++17:工程实用性明显增强
模板分支、值封装、视图类、文件系统进一步成熟。 -
C++20:语言与库继续体系化
概念约束、ranges、协程、同步原语继续完善。
2 基础语法与对象模型¶
解决:旧式基础写法不够安全、不够清晰,资源转移与对象语义表达不足。
-
右值引用 / move 语义 —— C++11
替代:不必要拷贝、资源转移成本高 -
nullptr —— C++11
替代:NULL / 0 造成的空指针歧义 -
range-based for —— C++11
替代:手写迭代器循环 -
enum class —— C++11
替代:传统枚举污染作用域、隐式转换过多 -
override / final —— C++11
替代:虚函数覆写靠人工检查,容易签名写错 -
=default / =delete —— C++11
替代:特殊成员函数行为表达不直接、禁止接口不明确 -
委托构造 / 继承构造 —— C++11
替代:构造逻辑重复、派生类构造转发啰嗦 -
统一初始化 —— C++11
替代:多套初始化语法并存、风格不统一 -
noexcept —— C++11
替代:异常规格写法弱且语义不清
C++11:把很多“旧 C++ 基础写法”整体换代
这一层不是炫技特性,而是现代 C++ 代码风格的底板
3 类型推导与泛型¶
解决:类型书写冗长、泛型表达能力不足、模板约束不清晰。
-
auto —— C++11
替代:显式长类型声明 -
decltype —— C++11
替代:模板上下文中手写复杂类型 -
using —— C++11
替代:typedef,尤其是模板别名场景下更自然 -
decltype(auto) —— C++14
替代:返回类型保真不足,容易丢引用 / cv 属性 -
泛型 lambda —— C++14
替代:手写仿函数、单独写模板函数对象 -
lambda init-capture —— C++14
替代:lambda 对 move-only 对象或初始化式捕获支持不足 -
类模板实参推导(CTAD)—— C++17
替代:显式写类模板参数 -
structured bindings —— C++17
替代:pair / tuple 返回值只能通过 first / second / get<> 拆解 -
concepts / requires —— C++20
替代:无约束模板、SFINAE、enable_if
C++11:开始“少写类型”,别名与接口表达更自然
C++14:让推导和泛型 lambda 更顺手
C++17:连模板实参和返回值拆解都开始简化
C++20:从“能写泛型”升级到“能约束泛型”
4 编译期能力与条件分发¶
解决:哪些逻辑能放到编译期、模板代码如何按条件分发、初始化约束如何表达。
-
constexpr —— C++11
替代:只能做很弱的编译期计算 -
static_assert —— C++11
替代:模板错误只能在深层报出、约束与假设难以前置表达 -
增强版 constexpr —— C++14
替代:早期 constexpr 可写性太弱 -
if constexpr —— C++17
替代:普通 if + 模板特化绕行、SFINAE 分发 -
fold expressions —— C++17
替代:参数包递归展开、模板样板代码 -
consteval / constinit —— C++20
替代:编译期求值要求不明确、静态初始化约束表达不清
C++11:constexpr 起步,但能力偏弱
C++14:constexpr 可写性增强
C++17:if constexpr 和 fold expressions 让模板代码更可读
C++20:进一步区分“必须编译期求值”和“静态初始化约束”
5 值语义与类型封装¶
解决:资源所有权、可空值表达、多类型封装、任意值承载、连续内存视图表达。
-
智能指针 —— C++11
替代:裸 new / delete、手工生命周期管理 -
std::optional —— C++17
替代:特殊值、bool + out 参数、部分值对象缺失场景下用空指针表达失败 -
std::variant —— C++17
替代:union + 手工维护活跃成员、部分基类指针 + dynamic_cast 分发 -
std::any —— C++17
替代:void* + 手工转型、弱约束通用承载
C++11:先解决资源管理标准化
C++17:补齐值封装工具
C++20:补齐连续内存的轻量视图表达
6 视图与范围表达¶
解决:拥有对象与非拥有视图分离,接口从“传具体容器”走向“传视图 / 传范围”。
-
std::string—— 基础能力
表示拥有数据的字符串对象 -
std::string_view—— C++17
替代:const std::string&到处传、const char*/std::string混杂接口 -
std::span—— C++20
替代:T* + size、多套数组 /vector/array接口 -
ranges —— C++20
替代:迭代器对 + 算法拼装分散、表达链路不直观
C++17:开始把“拥有数据”和“只读视图”分开表达
C++20:进一步把“数据范围”抽象出来,接口与算法表达更统一
7 工程与通用表达¶
解决:路径/文件操作标准化、格式化输出标准化、调用点信息标准化,以及部分通用表达能力的补齐。
-
std::filesystem —— C++17
替代:平台相关文件 API、手工拼路径字符串 -
inline variables —— C++17
替代:头文件中某些静态常量 / 模板静态成员定义不自然 -
std::format —— C++20
替代:sprintf / snprintf、字符串拼接 + 流式输出混用 -
std::source_location —— C++20
替代:手工传__FILE__ / __LINE__ / __func__ -
三路比较 <=> —— C++20
替代:成组手写比较运算符 -
designated initializers —— C++20
替代:聚合初始化时位置依赖强、可读性差 -
modules —— C++20
替代:头文件包含模型、编译依赖重、宏污染扩散
C++17:filesystem 进入标准库,工程能力明显增强
C++20:格式化、定位、比较、初始化、模块化表达继续补齐
8 并发与异步演进¶
解决:线程与互斥基础设施、多锁管理、线程协作同步、异步流程表达。
-
std::thread、mutex、lock_guard —— C++11
替代:平台私有线程接口、手工 lock / unlock -
std::unique_lock、condition_variable —— C++11
替代:更弱的锁控制方式、手工轮询 / 低层线程等待协调 -
future / promise / async —— C++11
替代:线程结果回传靠共享变量、手工协议传递异步结果 -
std::atomic —— C++11
替代:部分轻量同步场景下完全依赖 mutex -
std::scoped_lock —— C++17
替代:多个锁手工管理顺序 -
latch、barrier、semaphore —— C++20
替代:自旋、手工计数协议、弱抽象同步控制 -
jthread / stop_token —— C++20
替代:线程生命周期更难管理、缺乏统一取消语义 -
coroutines —— C++20
替代:回调链、手写状态机、拆碎的异步流程
C++11:并发基础设施进入标准库
C++17:锁管理进一步简化
C++20:同步原语更完整,线程取消语义开始标准化,协程进入语言层