✅ 本篇目标:
- 掌握 Concepts:写出清晰、可读、易调试的模板
- 使用 Ranges:以管道风格编写 STL 算法
- 初识 协程(Coroutines):简化异步与生成器
- 了解 模块(Modules):告别头文件,加速编译
- 实战整合:用 C++20 重写成绩分析系统
🕒 建议学习时间:3--4 小时|可分多次完成💡 本篇将让你站在 C++ 开发的最前沿!
📘 C++ 零基础入门教程(第 10 篇)
C++20 核心特性 ------ 编写更现代、更优雅的 C++
⚠️ 注意:需使用支持 C++20 的编译器(如 GCC 10+、Clang 13+、MSVC 19.29+)
第一步:Concepts ------ 给模板加上"类型约束"
❌ 传统模板的问题
cpp
template<typename T>
T add(T a, T b) {
return a + b;
}
int main() {
add(3, 5); // ✅ OK
add("Hi", "Bye"); // ❌ 编译失败!但错误信息长达百行!
}
🔥 问题:模板对类型无限制,错误信息晦涩难懂。
✅ C++20 Concepts:明确约束
cpp
#include <concepts>
// 定义概念:支持加法的类型
template<typename T>
concept Addable = requires(T a, T b) {
a + b; // 表达式必须合法
};
// 使用概念约束模板
template<Addable T>
T add(T a, T b) {
return a + b;
}
// 或更简洁(C++20 简写语法)
auto add2(Addable auto a, Addable auto b) {
return a + b;
}
✅ 现在调用 add("Hi", "Bye") 会得到清晰错误:
error: no matching function for call to 'add'
note: candidate template ignored: constraints not satisfied
常用标准概念(<concepts>)
| 概念 | 含义 |
|---|---|
std::integral<T> |
整数类型(int, long...) |
std::floating_point<T> |
浮点类型(float, double) |
std::equality_comparable<T> |
支持 == 和 != |
std::totally_ordered<T> |
支持 <, >, <=, >= |
示例:只接受数字类型
cpp
double average(std::floating_point auto x, std::floating_point auto y) {
return (x + y) / 2.0;
}
第二步:Ranges ------ STL 的现代化革命
❌ 传统 STL 算法:冗长、嵌套、难读
cpp
std::vector<int> nums = {1, 2, 3, 4, 5};
std::vector<int> evens;
// 找出偶数并平方
std::copy_if(nums.begin(), nums.end(), std::back_inserter(evens),
[](int x) { return x % 2 == 0; });
std::transform(evens.begin(), evens.end(), evens.begin(),
[](int x) { return x * x; });
✅ C++20 Ranges:管道式链式调用
cpp
#include <ranges>
#include <vector>
#include <iostream>
int main() {
std::vector<int> nums = {1, 2, 3, 4, 5};
auto result = nums
| std::views::filter([](int x) { return x % 2 == 0; })
| std::views::transform([](int x) { return x * x; });
for (int x : result) {
std::cout << x << " "; // 输出: 4 16
}
}
🔑 关键点:
|是管道操作符(类似 Linux shell)std::views::filter/transform返回惰性视图(不立即计算)- 内存高效,组合性强
常用 Views
| View | 作用 |
|---|---|
filter(pred) |
筛选满足条件的元素 |
transform(func) |
对每个元素应用函数 |
take(n) |
取前 n 个元素 |
drop(n) |
跳过前 n 个元素 |
reverse |
逆序 |
示例:取前 3 个大于 10 的偶数的平方
cpp
auto processed = data
| std::views::filter([](int x) { return x > 10 && x % 2 == 0; })
| std::views::transform([](int x) { return x * x; })
| std::views::take(3);
第三步:协程(Coroutines)--- 异步与生成器的新范式
协程允许函数暂停执行并稍后恢复,非常适合:
- 异步 I/O(网络、文件)
- 生成器(惰性序列)
- 状态机
💡 C++20 协程是底层机制,通常通过库(如 cppcoro)使用。
示例:生成器(Generator)
cpp
// 简化版生成器(需 cppcoro 或自定义)
generator<int> fibonacci() {
int a = 0, b = 1;
while (true) {
co_yield a; // 暂停并返回 a
auto next = a + b;
a = b;
b = next;
}
}
int main() {
auto gen = fibonacci();
for (int i = 0; i < 10; ++i) {
std::cout << *gen << " ";
++gen;
}
// 输出: 0 1 1 2 3 5 8 13 21 34
}
⚠️ 注意:标准库尚未提供
generator,但许多库已支持(如 Microsoft/cppcoro)。
第四步:模块(Modules)--- 告别头文件!
❌ 传统头文件的问题
- 重复包含(需
#ifndef) - 编译速度慢(每次都要解析头文件)
- 宏污染、符号冲突
✅ C++20 模块:干净、快速、安全
1. 创建模块(math.ixx 或 math.cppm)
cpp
// math.ixx
export module math;
export namespace math {
int add(int a, int b) {
return a + b;
}
double pi = 3.14159;
}
2. 导入模块
cpp
// main.cpp
import math;
import <iostream>;
int main() {
std::cout << math::add(2, 3) << "\n";
std::cout << math::pi << "\n";
}
3. 编译(GCC 示例)
bash
g++ -std=c++20 -fmodules-ts -xc++-system-header iostream
g++ -std=c++20 -fmodules-ts -c math.ixx -o math.o
g++ -std=c++20 -fmodules-ts main.cpp math.o -o app
🎯 优势:
- 编译速度提升 5--10 倍(实测)
- 无宏污染
- 明确导出接口(
export控制可见性)
第五步:实战整合 ------ C++20 成绩分析系统
我们将用 C++20 特性重写第 7 篇的成绩系统。
cpp
// grade_analysis_cpp20.cpp
import <iostream>;
import <vector>;
import <string>;
import <ranges>;
struct Student {
std::string name;
double score;
};
// 约束:Student 必须可比较分数
template<typename T>
concept HasScore = requires(T t) {
t.score;
requires std::floating_point<decltype(t.score)>;
};
auto getTopStudents(std::vector<Student> students, size_t topN) {
// 按分数降序排序
std::ranges::sort(students, std::greater{}, &Student::score);
// 取前 N 名(惰性)
auto topView = students
| std::views::take(topN)
| std::views::transform([](const Student& s) {
return s.name + ": " + std::to_string(s.score);
});
return std::vector<std::string>(topView.begin(), topView.end());
}
int main() {
std::vector<Student> students = {
{"Alice", 95}, {"Bob", 88}, {"Charlie", 92}, {"David", 97}
};
auto top3 = getTopStudents(students, 3);
for (const auto& info : top3) {
std::cout << info << "\n";
}
}
✅ 输出:
David: 97.000000
Alice: 95.000000
Charlie: 92.000000
🎉 亮点:
- 使用
std::ranges::sort直接按成员排序- 管道式数据处理,逻辑清晰
- 概念约束确保类型安全
📌 本篇小结:C++20 四大支柱
| 特性 | 价值 |
|---|---|
| Concepts | 模板约束,错误信息友好,接口清晰 |
| Ranges | 管道式 STL,组合性强,惰性求值 |
| 协程 | 简化异步、生成器、状态机 |
| 模块 | 替代头文件,加速编译,避免污染 |
🎓 全系列总结:你已成为现代 C++ 开发者!
| 阶段 | 能力 |
|---|---|
| 第 1--3 篇 | 掌握 C++ 基础与面向对象 |
| 第 4--5 篇 | 熟练使用 STL 与智能指针 |
| 第 6--7 篇 | 编写泛型、异常安全、可测试代码 |
| 第 8--9 篇 | 实现高性能并发与移动语义 |
| 第 10 篇 | 掌握 C++20,迈向未来 |
✅ 下一步建议
- 深入学习 :
- 《Effective Modern C++》 by Scott Meyers
- C++ Core Guidelines(isocpp.org)
- 参与开源:GitHub 上找 C++20 项目贡献
- 探索领域 :
- 游戏开发(Unreal Engine)
- 高频交易
- 嵌入式/系统编程
- 机器学习基础设施(PyTorch/TensorRT)
🌟 最后的话
从 cout << "Hello World"; 到 C++20 协程与模块 ,你走完了从零到现代 C++ 工程师的完整旅程。
C++ 是一门需要敬畏的语言,但也回报以极致的性能与控制力。
"C++ is not now and never has been a language for beginners."
--- Bjarne Stroustrup(C++ 之父)
坚持学习,持续实践,你完全有能力构建世界级的系统。
愿你的代码高效、安全、优雅!
------ C++ 零基础入门教程系列 完 ------