lru-2不能直接用std::list+std::unordered_map实现,因其需维护每个key的最近两次访问时间,而标准lru仅记录单次访问顺序;必须用两个unordered_map分别存最新和上一次访问时间,并在get/put时主动过期检查。

为什么不能直接用 std::list + std::unordered_map 实现 LRU-2?
LRU-2 的核心是记录每个 key 的**最近两次访问时间**,淘汰时优先踢掉「第二次最近访问」最久的那个;而标准 LRU(如 std::list + std::unordered_map)只维护一次访问顺序,无法区分「第一次 vs 第二次」访问。强行复用会导致误淘汰——比如某个 key 刚被访问两次,但第二次访问后立刻被新 key 挤出,它实际应保留在缓存中。
所以必须显式存储两个时间戳或两个访问序号。常见做法是用两个哈希表:一个存「最新访问时间」,一个存「上一次访问时间」,每次访问时滚动更新。
如何用两个 std::unordered_map 实现带过期的 LRU-2?
关键不是“双链表”,而是“双时间戳”+“过期检查时机”。过期不能只靠插入时检查(会漏掉长期未访问但已超时的项),必须在每次 get() 和 put() 时主动清理。
-
cache:主缓存,std::unordered_map<key std::pair std::chrono::steady_clock::time_point>></key>,存值和最后访问时间 -
lru2_history:记录每个 key 的上一次访问时间(即「倒数第二次」),类型同上 - 每次
get(key)时:先检查是否过期(对比当前时间与cache[key].second),过期则删掉该 key 并返回空;否则把当前时间写入lru2_history[key],再更新cache[key].second - 每次
put(key, value)时:同样先过期检查;若缓存满,遍历lru2_history找「上一次访问时间最早」的 key(注意:不是cache中的时间!),删除它及对应历史记录
过期时间怎么存才不拖慢性能?
别用 std::chrono::system_clock——时区/闰秒可能导致不可预测跳变;也别存绝对时间字符串。统一用 std::chrono::steady_clock::time_point,所有时间比较都基于同一时钟源。
过期阈值建议存为 std::chrono::milliseconds 或 std::chrono::seconds,避免每次计算都调用 duration_cast:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
class LRUTwoCache {
using Clock = std::chrono::steady_clock;
using TimePoint = Clock::time_point;
using Duration = std::chrono::milliseconds;
<pre class="brush:php;toolbar:false;">Duration ttl_;
TimePoint now() const { return Clock::now(); }};
在 get() 中判断:if (now() - entry.second > ttl_) {...} —— 这比存纳秒整数再做减法更安全、更可读。
LRU-2 淘汰逻辑容易错在哪几个点?
最容易忽略的是:淘汰时不能只看 lru2_history 里有记录的 key。刚插入的新 key 在 lru2_history 中没有上一次访问时间,按 LRU-2 规则它应被视为「只访问过一次」,优先级高于所有已有两次访问记录的 key——所以这类 key 的「上一次访问时间」应设为极早值(如 TimePoint::min()),确保它们在满时最先被淘汰。
- 插入新 key 时,必须同时往
lru2_history写入TimePoint::min(),而不是留空 - 淘汰循环中,对每个候选 key 都要确认它仍在
cache中(防止并发或中途被删) - 如果多个 key 共享同一「上一次访问时间」,需额外加随机扰动或按 key 哈希排序,避免总是踢同一个
真正麻烦的不是结构,而是时间语义的精确性:LRU-2 的“二级”本质是状态机(0次→1次→2次→…),而过期机制又给每个状态叠加了时间维度——这两者一旦没对齐,缓存就会漏数据或提前丢热 key。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










