本文按版本梳理现代 C++ 的核心特性、使用方法、工程价值和注意事项。
目录
- 版本演进概览
- C++11
- C++14
- C++17
- C++20
- 版本迁移建议
- 工程选型建议
- 面试高频问题
1. 版本演进概览
| 标准 | 重点 |
|---|---|
| C++11 | 现代 C++ 基础:移动语义、智能指针、线程、lambda |
| C++14 | 对 C++11 的完善:泛型 lambda、返回类型推导 |
| C++17 | 工程可用性增强:filesystem、optional、variant、string_view |
| C++20 | 模板、并发和语言结构升级:Concepts、Ranges、协程、模块 |
#mermaid-svg-zW6Z1kEvZDi2kVSi{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-zW6Z1kEvZDi2kVSi .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-zW6Z1kEvZDi2kVSi .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-zW6Z1kEvZDi2kVSi .error-icon{fill:#552222;}#mermaid-svg-zW6Z1kEvZDi2kVSi .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-zW6Z1kEvZDi2kVSi .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-zW6Z1kEvZDi2kVSi .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-zW6Z1kEvZDi2kVSi .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-zW6Z1kEvZDi2kVSi .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-zW6Z1kEvZDi2kVSi .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-zW6Z1kEvZDi2kVSi .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-zW6Z1kEvZDi2kVSi .marker{fill:#333333;stroke:#333333;}#mermaid-svg-zW6Z1kEvZDi2kVSi .marker.cross{stroke:#333333;}#mermaid-svg-zW6Z1kEvZDi2kVSi svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-zW6Z1kEvZDi2kVSi p{margin:0;}#mermaid-svg-zW6Z1kEvZDi2kVSi .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-zW6Z1kEvZDi2kVSi .cluster-label text{fill:#333;}#mermaid-svg-zW6Z1kEvZDi2kVSi .cluster-label span{color:#333;}#mermaid-svg-zW6Z1kEvZDi2kVSi .cluster-label span p{background-color:transparent;}#mermaid-svg-zW6Z1kEvZDi2kVSi .label text,#mermaid-svg-zW6Z1kEvZDi2kVSi span{fill:#333;color:#333;}#mermaid-svg-zW6Z1kEvZDi2kVSi .node rect,#mermaid-svg-zW6Z1kEvZDi2kVSi .node circle,#mermaid-svg-zW6Z1kEvZDi2kVSi .node ellipse,#mermaid-svg-zW6Z1kEvZDi2kVSi .node polygon,#mermaid-svg-zW6Z1kEvZDi2kVSi .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-zW6Z1kEvZDi2kVSi .rough-node .label text,#mermaid-svg-zW6Z1kEvZDi2kVSi .node .label text,#mermaid-svg-zW6Z1kEvZDi2kVSi .image-shape .label,#mermaid-svg-zW6Z1kEvZDi2kVSi .icon-shape .label{text-anchor:middle;}#mermaid-svg-zW6Z1kEvZDi2kVSi .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-zW6Z1kEvZDi2kVSi .rough-node .label,#mermaid-svg-zW6Z1kEvZDi2kVSi .node .label,#mermaid-svg-zW6Z1kEvZDi2kVSi .image-shape .label,#mermaid-svg-zW6Z1kEvZDi2kVSi .icon-shape .label{text-align:center;}#mermaid-svg-zW6Z1kEvZDi2kVSi .node.clickable{cursor:pointer;}#mermaid-svg-zW6Z1kEvZDi2kVSi .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-zW6Z1kEvZDi2kVSi .arrowheadPath{fill:#333333;}#mermaid-svg-zW6Z1kEvZDi2kVSi .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-zW6Z1kEvZDi2kVSi .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-zW6Z1kEvZDi2kVSi .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-zW6Z1kEvZDi2kVSi .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-zW6Z1kEvZDi2kVSi .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-zW6Z1kEvZDi2kVSi .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-zW6Z1kEvZDi2kVSi .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-zW6Z1kEvZDi2kVSi .cluster text{fill:#333;}#mermaid-svg-zW6Z1kEvZDi2kVSi .cluster span{color:#333;}#mermaid-svg-zW6Z1kEvZDi2kVSi div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-zW6Z1kEvZDi2kVSi .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-zW6Z1kEvZDi2kVSi rect.text{fill:none;stroke-width:0;}#mermaid-svg-zW6Z1kEvZDi2kVSi .icon-shape,#mermaid-svg-zW6Z1kEvZDi2kVSi .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-zW6Z1kEvZDi2kVSi .icon-shape p,#mermaid-svg-zW6Z1kEvZDi2kVSi .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-zW6Z1kEvZDi2kVSi .icon-shape .label rect,#mermaid-svg-zW6Z1kEvZDi2kVSi .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-zW6Z1kEvZDi2kVSi .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-zW6Z1kEvZDi2kVSi .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-zW6Z1kEvZDi2kVSi :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} C++11
现代化基础
C++14
语法完善
C++17
工程增强
C++20
泛型与并发升级
2. C++11 核心特性
2.1 auto
cpp
auto value = 42;
auto name = std::string("camera");
优点:
- 减少冗长类型;
- 避免重复;
- 便于处理迭代器、lambda 和模板类型。
注意:
cpp
const int value = 10;
auto copy = value; // copy 是 int,顶层 const 被移除
2.2 decltype
cpp
int x = 0;
decltype(x) y = 1;
适用于依赖表达式类型的泛型编程。
2.3 nullptr
cpp
void process(int);
void process(void*);
process(nullptr);
nullptr 具有专门的空指针类型,可避免 NULL 被当成整数的问题。
2.4 范围 for
cpp
for (const auto& item : items) {
process(item);
}
需要修改元素:
cpp
for (auto& item : items) {
item.normalize();
}
2.5 lambda
cpp
auto add = [](int a, int b) {
return a + b;
};
捕获:
cpp
int threshold = 10;
auto by_value = [threshold](int value) {
return value > threshold;
};
auto by_reference = [&threshold](int value) {
++threshold;
return value > threshold;
};
异步场景要注意引用捕获生命周期。
2.6 右值引用
cpp
std::string&& value = std::string("temporary");
右值引用为移动语义和完美转发提供基础。
2.7 移动语义
cpp
class Buffer {
public:
Buffer(Buffer&& other) noexcept
: data_(other.data_) {
other.data_ = nullptr;
}
private:
int* data_{nullptr};
};
移动语义可以转移资源而非深拷贝。
2.8 std::move
cpp
std::string source = "data";
std::string target = std::move(source);
std::move 只是将表达式转换为右值,不直接执行移动。
移动后对象仍然有效,但状态通常未指定,应只执行析构、重新赋值或文档允许的操作。
2.9 完美转发
cpp
template <typename T>
void wrapper(T&& value) {
target(std::forward<T>(value));
}
std::forward 保留参数的左值/右值属性。
2.10 智能指针
unique_ptr
cpp
auto engine = std::make_unique<Engine>();
shared_ptr
cpp
auto model = std::make_shared<Model>();
weak_ptr
cpp
std::weak_ptr<Model> observer = model;
2.11 统一初始化
cpp
int value{10};
std::vector<int> data{1, 2, 3};
花括号初始化可减少窄化转换:
cpp
int value{3.14}; // 编译错误
2.12 initializer_list
cpp
class TensorShape {
public:
TensorShape(std::initializer_list<int> dims)
: dims_(dims) {
}
private:
std::vector<int> dims_;
};
2.13 constexpr
cpp
constexpr int square(int value) {
return value * value;
}
允许在编译期求值。
2.14 static_assert
cpp
static_assert(sizeof(int) >= 4, "int too small");
在编译期验证假设。
2.15 override 与 final
cpp
class Base {
public:
virtual void run();
};
class Derived final : public Base {
public:
void run() override;
};
override 可帮助编译器检查是否真正重写。
2.16 委托构造
cpp
class Device {
public:
Device() : Device("default", 0) {
}
Device(std::string name, int id)
: name_(std::move(name)), id_(id) {
}
private:
std::string name_;
int id_;
};
2.17 默认和删除函数
cpp
class Resource {
public:
Resource() = default;
Resource(const Resource&) = delete;
Resource& operator=(const Resource&) = delete;
};
2.18 枚举类
cpp
enum class Status {
Ok,
Failed
};
优点:
- 不隐式转换为整数;
- 枚举值作用域受限;
- 类型更安全。
2.19 std::thread
cpp
std::thread worker([] {
runTask();
});
worker.join();
2.20 std::mutex
cpp
std::mutex mutex;
{
std::lock_guard<std::mutex> lock(mutex);
updateSharedState();
}
2.21 原子变量
cpp
std::atomic<bool> running{true};
2.22 chrono
cpp
const auto start = std::chrono::steady_clock::now();
run();
const auto elapsed =
std::chrono::steady_clock::now() - start;
2.23 unordered_map
cpp
std::unordered_map<std::string, int> scores;
提供平均 O(1) 查找。
2.24 类型特征
cpp
static_assert(std::is_integral<int>::value);
现代写法:
cpp
static_assert(std::is_integral_v<int>);
_v 变量模板来自 C++17。
3. C++14 核心特性
3.1 泛型 lambda
cpp
auto add = [](auto a, auto b) {
return a + b;
};
相当于匿名函数对象中的模板调用运算符。
3.2 lambda 初始化捕获
cpp
auto pointer = std::make_unique<int>(42);
auto task = [p = std::move(pointer)] {
return *p;
};
可将仅可移动对象捕获到 lambda。
3.3 函数返回类型推导
cpp
auto makeValue() {
return 42;
}
递归函数和多个不一致返回类型需额外注意。
3.4 decltype(auto)
cpp
decltype(auto) getValue(Container& container) {
return container.front();
}
可保留引用属性。
风险:
cpp
decltype(auto) bad() {
int value = 42;
return (value); // 返回 int&,悬空引用
}
3.5 变量模板
cpp
template <typename T>
constexpr T pi = T(3.1415926535897932385L);
3.6 二进制字面量
cpp
int mask = 0b10101010;
3.7 数字分隔符
cpp
int million = 1'000'000;
提高可读性。
3.8 std::make_unique
cpp
auto object = std::make_unique<Widget>();
这是 C++14 最常用的新特性之一。
3.9 更宽松的 constexpr
C++14 允许 constexpr 函数中包含更多语句:
cpp
constexpr int factorial(int n) {
int result = 1;
for (int i = 2; i <= n; ++i) {
result *= i;
}
return result;
}
4. C++17 核心特性
4.1 结构化绑定
cpp
std::pair<int, std::string> item{1, "apple"};
auto [id, name] = item;
遍历 map:
cpp
for (const auto& [key, value] : mapping) {
}
4.2 if 初始化语句
cpp
if (auto it = mapping.find(key);
it != mapping.end()) {
use(it->second);
}
变量作用域限制在 if/else 中。
4.3 switch 初始化语句
cpp
switch (auto code = getCode(); code) {
case 0:
break;
default:
break;
}
4.4 if constexpr
cpp
template <typename T>
void printValue(const T& value) {
if constexpr (std::is_integral_v<T>) {
std::cout << "integer: " << value;
} else {
std::cout << value;
}
}
未选择的分支不会被实例化。
4.5 std::optional
cpp
std::optional<int> findId(const std::string& name) {
if (name.empty()) {
return std::nullopt;
}
return 42;
}
适合"可能无值"的返回结果。
4.6 std::variant
cpp
using Value = std::variant<int, double, std::string>;
Value value = std::string("hello");
std::visit([](const auto& item) {
std::cout << item;
}, value);
可替代部分不安全的联合体和继承层次。
4.7 std::any
cpp
std::any value = 42;
int result = std::any_cast<int>(value);
灵活但类型检查发生在运行时,性能和可维护性通常不如 variant。
4.8 std::string_view
cpp
void logMessage(std::string_view message);
string_view 不拥有字符串,仅保存指针和长度。
必须注意生命周期:
cpp
std::string_view bad() {
return std::string("temporary");
}
上例返回悬空视图。
4.9 std::filesystem
cpp
namespace fs = std::filesystem;
for (const auto& entry : fs::directory_iterator(".")) {
std::cout << entry.path() << '\n';
}
支持:
- 路径处理;
- 文件查询;
- 目录遍历;
- 创建和删除目录;
- 文件大小和时间。
4.10 折叠表达式
cpp
template <typename... Args>
auto sum(Args... args) {
return (args + ...);
}
简化参数包操作。
4.11 类模板参数推导
cpp
std::pair pair(1, 2.0);
std::vector data{1, 2, 3};
编译器可推导模板参数。
4.12 内联变量
cpp
class Config {
public:
inline static int version = 1;
};
解决头文件中静态数据定义问题。
4.13 std::byte
cpp
std::byte value{0x1F};
用于表达原始字节,避免使用 char 带来的字符语义混淆。
4.14 并行算法
cpp
std::sort(
std::execution::par,
data.begin(),
data.end());
是否真正并行以及性能取决于实现和运行环境。
4.15 [[nodiscard]]
cpp
[[nodiscard]] Status initialize();
忽略返回值时编译器可发出警告。
5. C++20 核心特性
5.1 Concepts
cpp
template <typename T>
concept Number =
std::integral<T> ||
std::floating_point<T>;
template <Number T>
T add(T a, T b) {
return a + b;
}
优点:
- 约束模板参数;
- 错误信息更清晰;
- 提高接口表达能力。
5.2 requires
cpp
template <typename T>
requires requires(T value) {
value.size();
}
auto getSize(const T& value) {
return value.size();
}
可表达复杂编译期约束。
5.3 Ranges
cpp
auto even = data
| std::views::filter([](int value) {
return value % 2 == 0;
})
| std::views::transform([](int value) {
return value * value;
});
for (int value : even) {
}
Ranges 支持惰性组合和更强表达力。
5.4 协程
协程可以暂停和恢复函数执行,用于:
- 异步 I/O;
- 生成器;
- 任务调度;
- 状态机。
核心关键字:
cpp
co_await
co_yield
co_return
C++20 只提供语言基础,完整使用通常需要库或框架封装。
5.5 模块
cpp
export module math;
export int add(int a, int b) {
return a + b;
}
使用:
cpp
import math;
目标:
- 减少头文件重复解析;
- 改善依赖边界;
- 避免宏污染;
- 提升构建性能。
实际工程支持程度取决于编译器、构建系统和第三方库。
5.6 三路比较运算符
cpp
class Version {
public:
auto operator<=>(const Version&) const = default;
private:
int major_;
int minor_;
};
可自动生成比较关系。
5.7 指定初始化
cpp
struct Config {
int threads;
bool fp16;
};
Config config{
.threads = 4,
.fp16 = true
};
C++ 的指定初始化有顺序等限制,不等同于 C 的所有行为。
5.8 consteval
cpp
consteval int makeId(int value) {
return value * 100;
}
函数必须在编译期调用。
5.9 constinit
cpp
constinit int global_value = 42;
保证变量进行静态初始化,避免部分静态初始化顺序问题。
5.10 std::span
cpp
void normalize(std::span<float> values) {
}
span 是非拥有连续内存视图,可接受:
- C 数组;
std::array;std::vector;- 指针与长度。
5.11 std::jthread
cpp
std::jthread worker([](std::stop_token token) {
while (!token.stop_requested()) {
doWork();
}
});
析构时自动请求停止并 join()。
5.12 std::stop_token
用于协作式取消:
cpp
void task(std::stop_token token) {
while (!token.stop_requested()) {
}
}
5.13 同步原语
std::latch
一次性倒计时同步。
std::barrier
多阶段线程同步。
std::counting_semaphore
限制并发资源数量。
5.14 原子等待
cpp
std::atomic<int> state{0};
state.wait(0);
另一个线程:
cpp
state.store(1);
state.notify_one();
可减少传统条件变量的部分开销。
5.15 std::format
cpp
std::string message =
std::format("id={}, score={:.2f}", id, score);
提供类型安全格式化。不同编译器标准库的支持版本可能存在差异。
5.16 日历与时区扩展
std::chrono 增加:
- 日历类型;
- 日期运算;
- 时区相关支持。
实际时区数据库支持取决于标准库实现。
5.17 std::source_location
cpp
void log(
std::string_view message,
const std::source_location location =
std::source_location::current()) {
}
可自动获取:
- 文件名;
- 行号;
- 函数名。
5.18 std::bit_cast
cpp
float value = 1.0F;
std::uint32_t bits =
std::bit_cast<std::uint32_t>(value);
用于同大小、可平凡复制类型之间的位级转换。
5.19 std::endian
cpp
if constexpr (
std::endian::native ==
std::endian::little) {
}
用于判断本机字节序。
6. 特性对比
| 能力 | C++11 | C++14 | C++17 | C++20 |
|---|---|---|---|---|
| 移动语义 | ✓ | ✓ | ✓ | ✓ |
| 智能指针 | ✓ | ✓ | ✓ | ✓ |
| lambda | ✓ | 泛型 lambda | 完善 | 模板 lambda |
| 编译期计算 | constexpr | 更宽松 | if constexpr |
consteval/constinit |
| 文件系统 | - | - | filesystem | ✓ |
| 可选值 | - | - | optional | ✓ |
| 类型安全联合体 | - | - | variant | ✓ |
| 非拥有字符串视图 | - | - | string_view | ✓ |
| Concepts | - | - | - | ✓ |
| Ranges | - | - | - | ✓ |
| 协程 | - | - | - | ✓ |
| 模块 | - | - | - | ✓ |
| 自动停止线程 | - | - | - | jthread |
7. 工程迁移建议
7.1 C++98/03 到 C++11
优先替换:
NULL→nullptr- 裸
new/delete→ 智能指针 - 手工循环 → 范围
for - 自定义线程库 → 标准线程库
- 深拷贝资源类型 → 移动语义
- 宏常量 →
constexpr
7.2 C++11 到 C++14
重点采用:
make_unique- 泛型 lambda
- 初始化捕获
- 更宽松
constexpr
C++14 迁移成本通常较低。
7.3 C++14 到 C++17
重点采用:
optionalvariantstring_viewfilesystem- 结构化绑定
if constexprif初始化语句- 内联变量
C++17 是许多机器人、AI 部署和跨平台工程的成熟选择。
7.4 C++17 到 C++20
建议分阶段采用:
第一阶段:
- Concepts;
span;jthread;source_location;- 三路比较;
- 同步原语。
第二阶段:
- Ranges;
- 协程;
- Modules。
后者对工具链和团队学习成本要求更高。
8. 场景选型建议
| 场景 | 建议标准 |
|---|---|
| 旧版嵌入式编译器 | C++11/14 |
| ROS2 Humble | 通常 C++17 |
| AI 推理部署 | C++17 |
| 通用 Linux 服务 | C++17 或 C++20 |
| 新建高性能后端 | C++20 |
| SDK 兼容多平台 | C++14/17 |
| 需要 Concepts/Ranges | C++20 |
| 大量协程异步 I/O | C++20 |
标准选择应结合:
- 编译器;
- 标准库;
- 第三方依赖;
- 目标操作系统;
- ABI;
- 构建系统;
- 团队经验。
9. 高频面试问题
9.1 auto 和 decltype 的区别
auto 根据初始化表达式推导变量类型,通常会移除引用和顶层 const。
decltype 根据表达式规则直接得到类型,可保留引用和值类别信息。
9.2 std::move 是否保证移动
不保证。它只进行类型转换。最终是否调用移动构造取决于目标类型是否提供相应重载。
9.3 string_view 为什么危险
因为它不拥有数据。若底层字符串销毁、扩容或修改导致地址变化,string_view 可能悬空。
9.4 optional 和异常如何选择
optional 适合"没有结果是正常分支"。
异常适合不可恢复或需要跨多层传播的错误。
若需要详细错误信息,可使用状态对象或 expected 风格类型。
9.5 if constexpr 与普通 if
普通 if 两个分支都必须能通过编译。
if constexpr 未选中的分支在模板实例化时可被丢弃。
9.6 Concepts 的价值
Concepts:
- 为模板参数建立约束;
- 减少复杂 SFINAE;
- 提高错误信息质量;
- 增强接口可读性;
- 支持重载选择。
9.7 协程是不是线程
不是。协程是一种可暂停和恢复的函数执行机制。它可以在单线程或多线程调度器上运行。
9.8 Modules 是否完全替代头文件
目标上可减少传统头文件依赖,但现阶段工程通常仍需与传统头文件并存,特别是第三方库和跨平台构建场景。
10. 推荐学习顺序
#mermaid-svg-2sYv3ZmC2VSGqFvJ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-2sYv3ZmC2VSGqFvJ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .error-icon{fill:#552222;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .marker.cross{stroke:#333333;}#mermaid-svg-2sYv3ZmC2VSGqFvJ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-2sYv3ZmC2VSGqFvJ p{margin:0;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .cluster-label text{fill:#333;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .cluster-label span{color:#333;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .cluster-label span p{background-color:transparent;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .label text,#mermaid-svg-2sYv3ZmC2VSGqFvJ span{fill:#333;color:#333;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .node rect,#mermaid-svg-2sYv3ZmC2VSGqFvJ .node circle,#mermaid-svg-2sYv3ZmC2VSGqFvJ .node ellipse,#mermaid-svg-2sYv3ZmC2VSGqFvJ .node polygon,#mermaid-svg-2sYv3ZmC2VSGqFvJ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .rough-node .label text,#mermaid-svg-2sYv3ZmC2VSGqFvJ .node .label text,#mermaid-svg-2sYv3ZmC2VSGqFvJ .image-shape .label,#mermaid-svg-2sYv3ZmC2VSGqFvJ .icon-shape .label{text-anchor:middle;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .rough-node .label,#mermaid-svg-2sYv3ZmC2VSGqFvJ .node .label,#mermaid-svg-2sYv3ZmC2VSGqFvJ .image-shape .label,#mermaid-svg-2sYv3ZmC2VSGqFvJ .icon-shape .label{text-align:center;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .node.clickable{cursor:pointer;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .arrowheadPath{fill:#333333;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-2sYv3ZmC2VSGqFvJ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-2sYv3ZmC2VSGqFvJ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-2sYv3ZmC2VSGqFvJ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .cluster text{fill:#333;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .cluster span{color:#333;}#mermaid-svg-2sYv3ZmC2VSGqFvJ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-2sYv3ZmC2VSGqFvJ rect.text{fill:none;stroke-width:0;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .icon-shape,#mermaid-svg-2sYv3ZmC2VSGqFvJ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .icon-shape p,#mermaid-svg-2sYv3ZmC2VSGqFvJ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .icon-shape .label rect,#mermaid-svg-2sYv3ZmC2VSGqFvJ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-2sYv3ZmC2VSGqFvJ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-2sYv3ZmC2VSGqFvJ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-2sYv3ZmC2VSGqFvJ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} C++11 基础
移动语义与智能指针
lambda 与并发
C++14 完善特性
C++17 工程特性
C++20 Concepts 与 span
Ranges / 协程 / Modules
优先掌握:
- RAII;
- 智能指针;
- 移动语义;
- lambda;
- 标准线程库;
optional/variant/string_view;filesystem;- Concepts;
- Ranges;
- 协程与模块。