8
现代 C++ 特性巡礼(C++11 → 23)
Modern C++ Features
C++ 从 2011 年起每三年发一版,加了一堆让代码更短更安全的特性。不用一次全背,混个眼熟,写项目时知道"有这东西能查就行"。
| 特性(版本) | 一句话 |
|---|---|
| 右值引用 / 移动语义(C++11) | 临时对象的资源可以被"偷走"而不复制,vector 扩容快很多。 |
| 完美转发 std::forward(C++11) | 把参数原样转发给下一层,不改变左右值属性。 |
| =default / =delete(C++11) | =default 让编译器生成默认函数;=delete 禁止某个函数被调用。 |
| 用户自定义字面量(C++11) | 写 10s、3.14i 这种好看的字面量。 |
| 折叠表达式(C++17) | 可变参数模板的参数包一次性展开。 |
| if constexpr(C++17) | 编译期分支:模板里根据类型走不同代码,另一支直接不编译。 |
| 结构化绑定(C++17) | auto [a,b] = pair,前面见过。 |
| 三路比较 <=>(C++20) | 俗称"太空船运算符",一个运算符自动生成 < <= > >= 全套比较。 |
| 协程 coroutine(C++20) | co_await / co_yield / co_return,写异步、生成器超顺手。 |
| 模块 module(C++20) | 取代 #include,编译更快、不用头文件保护宏。 |
| ranges 范围库(C++20) | 管道式数据处理:v | view::filter | view::transform,像 Linux 管道。 |
| std::format(C++20) | 像 Python f-string 一样的格式化,比 printf 安全。 |
| std::print(C++23) | 直接打印到控制台的 format,告别 cout 一堆 <<。 |
ranges 管道 + format 的现代美感
#include <ranges>
#include <format>
#include <vector>
std::vector<int> v = {1, 2, 3, 4, 5, 6};
// 取偶数,再平方,用 | 串起来,像管道
auto result = v
| std::views::filter([](int x){ return x % 2 == 0; })
| std::views::transform([](int x){ return x * x; });
for (auto x : result)
std::print("{} ", x); // 4 16 36(C++23 的 print)
协程:能"暂停"和"恢复"的函数
普通函数一调用就跑到尾,中间不能停。协程(C++20)允许函数跑到一半挂起(suspend),把控制权交出去,等需要时再从挂起处接着跑——三个关键字 co_await(等异步结果)、co_yield(产出一个值再暂停)、co_return(协程返回)。它是写异步 I/O、生成器(generator)的大杀器,但概念较新,先认个脸。
co_yield 生成器的思路(概念示意)
// 一个"无限数列生成器":每被问一次,吐下一个数
// generator<int> naturals() {
// for (int i = 1; ; ++i)
// co_yield i; // 吐出 i,然后挂起;下次再来时从这里继续
// }
// 用法:auto g = naturals(); 每次 g.next() 拿到 1, 2, 3 ...
// 不用真的写一个 vector 存所有数——这就是协程省内存的地方。
辨协程 vs 线程
线程是操作系统调度的,切换贵、还要抢锁;协程是程序自己协作式让出的,切换极轻量,单线程里就能跑成千上万个"任务"。现代高并发服务(如网络框架)越来越多用协程替代线程池。C++20 的协程是底层构件,日常多用现成库(如asio),不必自己手写框架。