引言
C++20 是 C++ 标准的一个重大更新,引入了许多革命性特性,这些特性不仅提升了代码的表达力和效率,还在泛型编程、异步操作和标准库方面带来了显著改善。作为一名资深开发者,我将按应用场景详细介绍 C++20 的十大新特性,每个特性包括功能模块的详细说明和嵌入的代码示例。这些特性协助开发者在实际项目中解决复杂问题,提高代码的可维护性和性能。文章将覆盖模块化编程、约束泛型、协程、范围库、三路比较运算符、格式化库、日历与时区、span、指定初始化器以及 Lambda 增强。以下内容将逐一展开,每个部分结合实际应用场景,提供深入分析和代码示范,确保开发者能快速上手并应用到项目中。

1. Modules(模块)
应用场景
Modules 主要应用于大型项目中的代码组织和重用场景。例如,在开发一个数学库或图形引擎时,可以将接口和实现分离,提高编译速度并避免头文件依赖问题。在企业级软件开发中,Modules 可以减少宏污染和名称冲突,提升模块化设计,尤其适合微服务架构或多团队协作的项目。在构建系统如 CMake 或 Bazel 中,Modules 能显著缩短增量编译时间,对于持续集成/持续部署 (CI/CD) 管道特别有益。此外,在嵌入式系统开发中,Modules 协助隔离硬件相关代码,提高可移植性。
详细说明
Modules 解决了传统头文件系统的痛点,如重复编译和宏泄露。通过 export 和 import 关键字,开发者可以定义模块接口单元和实现单元。模块接口单元使用 export module 声明导出实体,实现单元则不导出。模块分区允许进一步细分模块,使用冒号语法。全局模块片段用于处理宏依赖的头文件,放置在模块单元开头。私有模块片段限制访问性,仅模块内部可见。编译时,模块文件被编译成二进制,提高效率。模块不影响宏可见性,确保封装。标准库模块如 std.core 可直接导入。功能模块包括:接口定义、实现分离、分区管理和导入机制。这些模块共同提升了代码的封装性和构建性能。
代码示例
// math.cppm - 模块接口单元
export module math;
export int add(int a, int b) { return a + b; }
export int multiply(int a, int b) { return a * b; }
// main.cpp
import math;
#include <iostream>
int main() {
std::cout << "Addition: " << add(3, 5) << std::endl;
std::cout << "Multiplication: " << multiply(2, 4) << std::endl;
return 0;
}
在实际应用中,这种方式可以显著缩短构建时间,尤其在处理数千文件的大型项目中。编译命令示例:g++ -std=c++20 -c math.cppm,然后链接 main.cpp。
2. Concepts(概念)
应用场景
Concepts 适用于泛型编程场景,如模板函数或类需要特定类型约束时。例如,在科学计算库中,确保模板参数支持积分运算,避免编译时错误。在模板重载和 SFINAE 替代中,Concepts 简化代码。在 STL 扩展或自定义容器开发中,使用 Concepts 定义接口要求,提高库的可扩展性。在游戏开发中,约束渲染模板参数为浮点类型,确保性能。在机器学习框架中,Concepts 用于验证张量类型,支持多后端兼容。
详细说明
Concepts 定义模板参数的约束,使用 requires 子句或 concept 关键字。包括合取(&&)、析取(||)和原子约束。标准库提供如 integral、same_as、derived_from 等概念。Concepts 提升错误消息的可读性,并支持概念重载。功能模块包括:约束定义(concept 关键字)、requires 子句应用、标准概念库和概念在模板中的使用。这些模块使泛型代码更安全、更易调试。Concepts 还支持嵌套约束和表达式要求,如 requires { ++t; } 检查可递增性。
代码示例
#include <concepts>
#include <iostream>
template <typename T>
concept Integral = std::integral<T>;
template <Integral T>
void print(T value) {
std::cout << "Integral value: " << value << std::endl;
}
int main() {
print(42); // 有效
// print(3.14); // 编译错误:不满足 Integral 概念
return 0;
}
这种约束在库设计中防止无效实例化,提高代码的鲁棒性。另一个示例:使用 convertible_to 概念确保类型转换安全。
3. Coroutines(协程)
应用场景
Coroutines 适合异步编程,如网络 I/O、游戏循环或生成器。在 Web 服务器中,使用协程处理非阻塞请求,提升吞吐量。在数据流处理中,实现懒惰计算的无限序列。在 GUI 应用中,协程用于动画或长任务,避免 UI 冻结。在模拟系统中,协程模拟并发行为而无需多线程开销。
详细说明
协程是栈无关的,使用 co_await、co_yield 和 co_return。包括 promise 对象(处理结果)、协程句柄(恢复/销毁)和状态(动态分配)。悬挂时返回调用者,恢复时继续执行。限制包括不能用于 constexpr 或 main 函数。功能模块包括:promise_type 定义、awaitable 对象、悬挂点管理和异常处理。这些模块支持合作式多任务,提高异步代码的可读性。动态分配可优化为栈嵌入。
代码示例
#include <coroutine>
#include <iostream>
#include <thread>
struct task {
struct promise_type {
task get_return_object() { return {}; }
std::suspend_never initial_suspend() { return {}; }
std::suspend_never final_suspend() noexcept { return {}; }
void return_void() {}
void unhandled_exception() {}
};
};
auto switch_to_new_thread(std::jthread& out) {
struct awaitable {
std::jthread* p_out;
bool await_ready() { return false; }
void await_suspend(std::coroutine_handle<> h) {
std::jthread& out = *p_out;
out = std::jthread([h] { h.resume(); });
}
void await_resume() {}
};
return awaitable{&out};
}
task my_coroutine() {
std::jthread out;
co_await switch_to_new_thread(out);
std::cout << "Coroutine on new thread" << std::endl;
}
int main() {
my_coroutine();
return 0;
}
协程在异步任务中减少回调地狱,提升代码线性度。
4. Ranges(范围库)
应用场景
Ranges 用于数据处理管道,如过滤、转换序列。在机器学习中,处理数据集;在 GUI 应用中,操作列表视图。在大数据分析中,组合视图进行懒惰计算,节省内存。在游戏中,处理实体列表如过滤可见对象。
详细说明
Ranges 抽象序列,提供视图和适配器。支持懒惰计算,组合如 filter、transform、take。概念如 sized_range、view 分类范围。功能模块包括:范围访问(begin/end)、原始类型(iterator_t)、视图工厂(iota_view)和适配器(join_view)。这些模块使算法更可组合,减少错误。
代码示例
#include <ranges>
#include <vector>
#include <iostream>
int main() {
std::vector<int> v = {1, 2, 3, 4, 5};
auto even = v | std::views::filter([](int i){ return i % 2 == 0; })
| std::views::transform([](int i){ return i * 2; });
for (int i : even) std::cout << i << ' ';
return 0;
}
Ranges 提升算法的组成性,适用于链式操作。
5. Three-way Comparison Operator(三路比较运算符)
应用场景
用于自定义类型比较,如排序算法或容器。在游戏开发中,比较对象位置;在数据库查询中,优化比较。在 STL 容器中,默认生成比较,提升效率。在版本控制系统中,比较文件差异。
详细说明
<=> 运算符返回 strong_ordering 或 partial_ordering。简化比较实现,支持默认生成。处理浮点 NaN 和指针。功能模块包括:运算符重载、ordering 类型和默认比较。这些模块减少 boilerplate 代码,支持多类型。
代码示例
#include <compare>
#include <iostream>
struct Point {
int x, y;
auto operator<=>(const Point&) const = default;
};
int main() {
Point p1{1,2}, p2{3,4};
if (p1 <=> p2 < 0) std::cout << "p1 < p2";
return 0;
}
减少了手动实现 <、> 等运算符的需要。
6. std::format(格式化库)
应用场景
日志记录、字符串构建。在 CLI 工具中,格式化输出;在报告生成中,动态字符串。在国际化中,支持本地化格式。在调试工具中,格式化变量输出。
详细说明
提供安全格式化,类似 Python format。支持运行时和编译时检查。功能模块包括:format 函数、format_to、formatter 扩展和异常处理。这些模块提升字符串处理安全性,支持自定义类型。
代码示例
#include <format>
#include <string>
#include <iostream>
int main() {
std::string msg = std::format("The answer is {}.", 42);
std::cout << msg << std::endl;
return 0;
}
比 printf 更安全,避免类型错误。
7. Calendar and Time Zones in <chrono>(日历与时区)
应用场景
日期计算、调度系统。在金融应用中,处理时区转换;在日程软件中,管理事件。在日志系统中,时间戳转换。在全球应用中,确保时区一致性。
详细说明
添加 year、month 等类,支持 Gregorian 日历。时区使用 tzdb、zoned_time 和 leap_second。功能模块包括:日历组件、时区数据库、zoned_time 和异常。这些模块标准化时间处理,支持 IANA 数据库。
代码示例
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono;
auto ymd = year{2023}/month{3}/day{15};
std::cout << ymd << std::endl;
return 0;
}
处理复杂日期操作简便。
8. std::span(span)
应用场景
非拥有视图,如函数参数传递数组。在图像处理中,操作像素缓冲;在 API 中,避免拷贝。在性能关键代码中,传递子数组。
详细说明
引用连续序列,支持静态/动态范围。提供子视图如 first、last。功能模块包括:元素访问、观察者和子视图。这些模块提升效率和安全性,避免所有权问题。
代码示例
#include <span>
#include <vector>
void process(std::span<int> s) {
for (int& i : s) i *= 2;
}
int main() {
std::vector<int> v = {1,2,3};
process(v);
return 0;
}
高效传递视图而不拷贝。
9. Designated Initializers(指定初始化器)
应用场景
初始化复杂结构体,如配置对象。在嵌入式系统中,初始化硬件寄存器。在数据结构中,部分初始化成员。
详细说明
允许命名成员初始化,未提成员值初始化。支持数组和结构体。功能模块包括:成员指定、数组索引和部分初始化。这些模块提高可读性,减少顺序依赖。
代码示例
#include <string>
struct Person {
std::string name;
int age;
};
int main() {
Person p = { .name = "John", .age = 30 };
return 0;
}
使初始化更直观。
10. Lambda Enhancements(Lambda 增强)
应用场景
泛型 Lambda 在算法中;默认构造在容器存储。在元编程中,使用模板 Lambda;在回调系统中,默认构造简化。
详细说明
支持模板参数和无捕获默认构造。功能模块包括:模板参数列表、默认构造函数和约束。扩展 Lambda 用途,接近函数模板。
代码示例
auto gl = []<typename T>(T a, auto&& b) { return a < b; };
int main() {
bool res = gl(1, 2.0);
return 0;
}
提升 Lambda 的泛型能力。
结语
C++20 这些特性重塑了编程实践,协助开发者构建更高效、更安全的代码。





![[C++探索之旅] 第一部分第十一课:小练习,猜单词 - 鹿快](https://img.lukuai.com/blogimg/20251015/da217e2245754101b3d2ef80869e9de2.jpg)










- 最新
- 最热
只看作者