C++20继 C++11 之后最具革命性的 C++ 标准
C++20(ISO/IEC 14882:2020)是继 C++11 之后最具革命性的 C++ 标准更新,引入了 四大核心特性(Modules、Concepts、Ranges、Coroutines)以及数十项语言与库的增强,显著提升了代码的安全性、表达力、性能和可维护性。
以下是对 C++20 新特性的全面、系统化总结,涵盖语言核心、标准库、实用示例及工程价值。
一、设计目标
- 解决长期痛点
:头文件编译慢、模板错误难读、异步编程复杂
- 现代化泛型编程
:让模板像普通函数一样易用
- 提升并发与数据处理能力
- 为未来 C++23/26 奠定基础
✅ C++20 被誉为 “Modern C++ 的新起点”。
二、四大核心特性(The Big Four)
1. 模块(Modules) —— 头文件的终结者
🎯 目标
-
解决
#include导致的重复解析、宏污染、编译速度慢问题。 -
提供强封装(内部细节不暴露)、无命名冲突的代码组织方式。
🔧 语法
// math.ixx (模块接口单元)
export module math;
export int add(int a, int b) {
return a + b;
}
// 不导出的辅助函数(外部不可见)
int helper() { return 42; }
// main.cpp
import math;
import <iostream>; // C++20 也支持导入标准库模块(部分编译器)
int main() {
std::cout << add(2, 3); // OK
// helper(); // ❌ 编译错误:未导出
}
✅ 优势
- 编译速度提升 5–10 倍
(接口只编译一次)
- 无宏泄漏
(模块内宏不影响外部)
- 清晰的 API 边界
⚠️ 编译器支持:MSVC(完整)、Clang(≥16)、GCC(≥13,实验性)
2. 概念(Concepts) —— 模板的类型约束
🎯 目标
-
为模板参数提供编译期类型约束
-
使模板错误信息清晰可读
-
支持基于约束的函数重载
🔧 语法
#include <concepts>
// 定义概念
template<typename T>
concept Integral = std::is_integral_v<T>;
// 使用概念约束模板
template<Integral T>
T add(T a, T b) {
return a + b;
}
// 或使用 requires 子句
template<typename T>
requires std::floating_point<T>
T divide(T a, T b) { return a / b; }
// 自动推导(C++20 简写)
auto multiply(std::integral auto a, std::integral auto b) {
return a * b;
}
✅ 优势
-
错误提示从“模板实例化失败”变为“类型 X 不满足 Concept Y”
-
支持语义化重载
void sort(Sortable auto& container); // 仅接受可排序容器
void print(Printable auto value); // 仅接受可打印类型
📌 标准库提供大量预定义概念:
std::integral,std::equality_comparable,std::random_access_iterator等。
3. 范围(Ranges) —— STL 的现代化升级
🎯 目标
-
统一容器与算法接口
-
支持管道操作(|) 和惰性求值
-
避免中间临时容器
🔧 语法
#include <ranges>
#include <vector>
#include <iostream>
std::vector<int> vec = {1, 2, 3, 4, 5, 6};
// 管道操作:过滤偶数 → 平方 → 取前2个
auto result = vec
| std::views::filter([](int n) { return n % 2 == 0; })
| std::views::transform([](int n) { return n * n; })
| std::views::take(2);
for (int x : result) {
std::cout << x << " "; // 输出:4 16
}
✅ 核心组件
|
组件 |
说明 |
|---|---|
std::views::filter |
过滤元素 |
std::views::transform |
映射转换 |
std::views::take/drop |
截取子范围 |
std::ranges::sort |
范围版排序(无需 begin/end) |
⚠️ 视图(View)是惰性的:不存储数据,不立即计算,仅在遍历时按需生成。
4. 协程(Coroutines) —— 轻量级异步编程
🎯 目标
-
简化异步/生成器代码
-
避免“回调地狱”
-
实现挂起与恢复的函数
🔧 关键字
co_await:等待异步操作
co_yield:生成值并挂起(用于生成器)
co_return:返回协程结果
📌 示例:生成器
#include <coroutine>
#include <iostream>
struct Generator {
struct promise_type {
int current_value;
auto get_return_object() { return Generator{Handle::from_promise(*this)}; }
auto initial_suspend() { return std::suspend_always{}; }
auto final_suspend() noexcept { return std::suspend_always{}; }
void unhandled_exception() { std::terminate(); }
auto yield_value(int value) {
current_value = value;
return std::suspend_always{};
}
void return_void() {}
};
using Handle = std::coroutine_handle<promise_type>;
Handle coro;
bool next() {
if (!coro.done()) coro.resume();
return !coro.done();
}
int value() { return coro.promise().current_value; }
~Generator() { if (coro) coro.destroy(); }
};
Generator iota(int start) {
for (int i = start; ; ++i)
co_yield i;
}
// 使用
auto gen = iota(10);
for (int i = 0; i < 3; ++i) {
gen.next();
std::cout << gen.value() << " "; // 10 11 12
}
⚠️ 协程本身不提供调度器,需结合
std::future、第三方库(如 cppcoro)或自定义awaiter。
三、其他重要语言特性
1. 三路比较运算符(<=>,Spaceship Operator)
自动生成全部比较运算符:
struct Point {
int x, y;
auto operator<=>(const Point&) const = default;
};
Point a{1, 2}, b{3, 4};
bool cmp = (a < b); // 自动按字典序比较
2. constexpr 增强
-
允许
virtual函数、try-catch(但异常必须在编译期处理) -
支持 动态内存分配(
new/delete,但必须配对)
constexpr int sum_array() {
int* arr = new int[3]{1, 2, 3};
int s = arr[0] + arr[1] + arr[2];
delete[] arr;
return s;
}
static_assert(sum_array() == 6);
3. Lambda 捕获增强
-
允许
[*this]捕获当前对象副本 -
模板参数可用于 Lambda:
auto f = []<typename T>(T x) { return x * 2; };
4. 范围 for 循环初始化语句
for (auto v = getVector(); auto& x : v) {
x *= 2;
}
四、标准库重大增强
1. std::format —— 类型安全的格式化(替代 printf/iostream)
#include <format>
std::string s = std::format("Hello {}! Pi ≈ {:.2f}", "World", 3.14159);
// 输出:Hello World! Pi ≈ 3.14
2. std::span —— 非拥有式连续内存视图
void process(std::span<int> data) {
for (int x : data) std::cout << x;
}
std::vector<int> v = {1,2,3};
int arr[] = {4,5,6};
process(v); // OK
process(arr); // OK
3. std::jthread —— 自动加入的线程(RAII)
#include <thread>
void task(std::stop_token st) {
while (!st.stop_requested()) {
// 工作
}
}
std::jthread t(task); // 析构时自动 request_stop() + join()
4. 日历与时区(<chrono> 扩展)
using namespace std::chrono;
auto now = system_clock::now();
auto tomorrow = floor<days>(now) + days{1};
std::cout << std::format("{:%F}", tomorrow); // 2025-12-19
5. 位操作库(<bit>)
#include <bit>
uint32_t x = 0x12345678;
uint32_t y = std::byteswap(x); // 小端 ↔ 大端
int cnt = std::popcount(x); // 计算 1 的个数
6. 原子智能指针
std::atomic<std::shared_ptr<int>> ptr;
ptr.store(std::make_shared<int>(42));
auto local = ptr.load(); // 原子读取
五、弃用与移除
|
特性 |
状态 |
|---|---|
<std::raw_storage_iterator> |
移除 |
<std::unary_function>
/ |
移除 |
std::result_of |
弃用(用 |
六、C++20 vs C++17 对比速查
|
特性 |
C++17 |
C++20 |
|---|---|---|
|
模块(Modules) |
❌ |
✅ |
|
概念(Concepts) |
❌ |
✅ |
|
范围(Ranges) |
❌ |
✅ |
|
协程(Coroutines) |
❌ |
✅ |
std::format |
❌ |
✅ |
std::span |
❌ |
✅ |
std::jthread |
❌ |
✅ |
|
三路比较 |
❌ |
✅ |
constexpr
动态内存 |
❌ |
✅ |
七、最佳实践建议
- 新项目优先考虑 Modules
(尤其大型工程)
- 用 Concepts 约束模板
,提升可读性与错误提示
- 用 Ranges 重构 STL 算法
,代码更简洁
- 协程用于 I/O 密集型任务
(非 CPU 密集)
- 用
std::format替代sprintf/cout - 函数参数优先使用
span而非指针+size
八、总结
C++20 是一次范式升级:
它不仅添加了新功能,更改变了 C++ 的编程风格——从“模板元编程黑魔法”走向“清晰、安全、高效”的现代范式。
尽管编译器支持仍在完善(截至 2025 年底,MSVC 最完整,GCC/Clang 逐步跟进),但核心特性已可投入生产环境。
如需深入探讨以下主题,欢迎关注交流:
-
如何迁移现有项目到 Modules?
-
Ranges 与传统 STL 性能对比?
-
协程与 async/await 模型的关系?
-
Concepts 与 SFINAE 的选型?
祝你驾驭 C++20,写出更优雅的现代 C++ 代码!
更多推荐
所有评论(0)