fifo页面置换必须同时使用队列和哈希集合:std::queue记录顺序,std::unordered_set支持o(1)缺页判断;仅用queue会导致查找o(m)、命中误判、淘汰遗漏;缺页率分母恒为访问序列总长度n。

FIFO 页面置换不能只靠 std::queue 就完事——缺页判断会失效,命中率必然算错。
为什么 std::queue 单独用在 FIFO 中会出致命问题
因为 std::queue 只管插入和弹出顺序,不提供 O(1) 查找能力。每次访问页面时,你必须立刻回答:“这个页号当前是否已在内存中?”——否则就无法区分命中与缺页。
- 仅用
std::queue存页号 → 每次查驻留状态得遍历整个队列,时间复杂度升到O(m)(m是物理块数) - 用
std::queue但没同步维护驻留集合 → 命中时仍会重复装入,missingCount虚高 - 淘汰后没从集合中移除旧页 → 后续再访问该页会被误判为缺页,二次计数
必须配对使用的两个核心结构:队列 + 驻留集合
逻辑上 FIFO 需要两个不可分割的组件:一个记录“谁先进来”的顺序(队列),一个支持“有没有它”的快速查询(哈希集合)。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 推荐组合:
std::queue<int></int>+std::unordered_set<int></int> - 插入新页时:
queue.push(pageId)且residentSet.insert(pageId) - 淘汰页时:
int victim = queue.front(); queue.pop(); residentSet.erase(victim) - 查命中:
if (residentSet.find(pageId) != residentSet.end())—— 这才是 O(1)
循环数组实现时 cur 下标更新的三个硬约束
若用 std::vector<int></int> 模拟循环队列(更省内存、避免指针分配),cur 不是随便加一取模就能跑通的。
-
cur仅在发生缺页且内存已满时才更新:cur = (cur + 1) % m - 数组必须严格按物理块数
m分配,且初始化为全-1或空值,否则越界写入会覆盖相邻变量 - 首次装入阶段(内存未满)不能动
cur,否则逻辑头部错位,导致最早装入的页被跳过淘汰
缺页率计算里最容易被忽略的分母陷阱
缺页率 = missingCount / pages.size(),不是“有效访问次数”,也不是“去重后页数”,更不是“填满后的访问次数”。
- 输入序列长度为
n,分母就是n,雷打不动 - 哪怕前
m次访问全是缺页(内存从空到满),这m次都计入分母 - 某页第一次访问缺页(计入分子),第二次命中(不计入分子,但计入分母)→ 这两次都参与除法
真正容易崩的是“把首次装入当成初始化跳过统计”,这会让分母变小,缺页率人为虚高;而 FIFO 的调度意义,恰恰始于第一次装入中断。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










