现代 C++ 实战(26):LRU 缓存与 JSON 解析器
第 25 篇 给服务加了持久化;本篇是两个经典练手项目:LRU 缓存练数据结构设计,JSON 解析器练递归下降与 std::variant——都是面试高频、又能深入理解 C++ 现代特性。
demo:ref/cpp_demo/projects/learning_guide/(lru_cache/ + json_parser/)。
这是「现代 C++ 实战」系列的第 26 篇。建议先读 第 20 篇:栈、队列与链表(LRU 底层)和 第 24 篇:HTTP 服务与 JSON(nlohmann/json)。
一、LRU 缓存:设计思路
LRU(Least Recently Used)——缓存满时淘汰最久未使用的项。要求 get 和 put 均 O(1)。
1 | unordered_map<K, iterator> list<pair<K,V>> |
| 组件 | 作用 |
|---|---|
std::list |
维护访问顺序,支持 O(1) 移动 |
std::unordered_map |
key → list 迭代器,O(1) 查找 |
list::splice |
将节点移到头部,迭代器不失效 |
二、LRU 核心实现
1 | template<typename K, typename V> |
现代 C++ 特性一览:
| 特性 | 用途 |
|---|---|
std::optional<V> |
get 未命中返回 nullopt |
std::move |
put 避免值拷贝 |
[[nodiscard]] |
强制检查返回值 |
| 删除拷贝 / 默认移动 | 避免迭代器失效 |
demo 还实现了 LRUCacheWithCallback——淘汰时触发回调,适合资源清理场景。
三、LRU 应用场景
| 场景 | 说明 |
|---|---|
| DNS 缓存 | 域名 → IP,减少查询延迟 |
| 页面缓存 | Web 服务器热点数据 |
| 数据库缓冲池 | 磁盘页缓存 |
| CPU Cache | 硬件级 LRU 近似 |
demo 模拟 DNS 缓存:第一次查询走慢路径,第二次缓存命中。
四、JSON 解析器:递归下降
第 24 篇 用 nlohmann/json 开箱即用;本篇手写解析器理解原理。
JSON 文法(简化):
1 | value := null | bool | number | string | array | object |
每个规则对应一个解析函数——递归下降:
1 | JsonValue parse_value() { |
parse_array 和 parse_object 递归调用 parse_value(),自然处理任意嵌套。
五、std::variant 表示 JSON 值
1 | using JsonVariant = std::variant< |
| JSON 类型 | C++ 类型 | variant index |
|---|---|---|
| null | std::monostate |
0 |
| boolean | bool |
1 |
| number | double |
2 |
| string | std::string |
3 |
| array | vector<JsonValue> |
4 |
| object | map<string, JsonValue> |
5 |
访问方式:
1 | // std::visit + if constexpr |
六、移动语义在解析中的应用
构建嵌套 JSON 时用 std::move 避免深拷贝:
1 | JsonArray arr; |
字符串解析末尾:
1 | return JsonValue(std::move(result)); // 长字符串移动更高效 |
七、错误处理
1 | class JsonParseError : public std::runtime_error { |
常见错误:尾随逗号、单引号、未闭合括号、undefined。
八、与 nlohmann/json 对比
| 手写解析器 | nlohmann/json | |
|---|---|---|
| 目的 | 学习、可控 | 生产使用 |
| 依赖 | 无(仅 STL) | 头文件库 |
| 性能 | demo 级 | 高度优化 |
| API | 自定义 | 成熟生态 |
工程上直接用 nlohmann/json;理解递归下降和 variant 后,读任何 JSON 库源码都更容易。
九、运行 demo
1 | cd ref/cpp_demo/projects/learning_guide |
LRU 演示:基本操作、淘汰策略、DNS 缓存、性能测试(百万次 put/get)。
JSON 演示:基本类型、嵌套结构、std::visit、错误处理、序列化 dump()、与 nlohmann 对比。
十、小结
| 项目 | 要点 |
|---|---|
| LRU | unordered_map + list + splice,O(1) get/put |
| JSON 解析 | 递归下降,一文法一函数 |
| JsonValue | std::variant 六种类型 |
| 移动语义 | 嵌套结构构建时避免拷贝 |
| 工程选型 | 学习手写,生产用 nlohmann/json |
下一篇进入系列收官:C++20 协程与 Actor 模型——见 第 27 篇:协程与 Actor 模型(计划)。










