std::queue 单独无法实现正确 FIFO 页面置换,因其无 find 接口、不支持迭代器遍历,且无法维护真实驻留状态,导致命中判断错误和假缺页;必须配合 std::unordered_set 同步更新以保证正确性。

单独用 std::queue 实现 FIFO 页面置换,命中率一定算错——它不维护驻留状态,查“页是否已在内存”只能遍历,淘汰后旧页号还留在逻辑集合里,后续访问持续误判缺页。
为什么 std::queue 单独不能判断命中
因为 std::queue 没有 find() 成员函数,写 q.find(page) 直接编译失败。退而求其次用 std::find(q.begin(), q.end(), page)?不行:std::queue 不提供迭代器接口,根本没法遍历。真要硬扫,得先倒进 std::vector 再查,单次开销从 O(1) 变成 O(m),m=64 时就是 64 次比较+拷贝。更糟的是:队列里可能存着已被淘汰但没清理的页号,“假驻留”导致同一页面连续访问(如 0 0 0)全判缺页。
std::queue + std::unordered_set 必须严格同步更新
这不是“推荐搭配”,是硬性闭环:一个管谁最老,一个管谁还在。漏掉任意一环就崩:
- 装入新页时:
pageQueue.push(page)✅ 且inMemory.insert(page)✅ - 淘汰旧页时:
int victim = pageQueue.front()→pageQueue.pop()✅ → 立即inMemory.erase(victim)✅ - 查命中只用
inMemory.find(page) != inMemory.end(),绝不动pageQueue - 调用
pageQueue.front()前必须检查!pageQueue.empty(),尤其frameCount == 0或序列极短时
手写循环数组时 cur 指针的三个硬约束
用 std::vector<int> frames(frameCount, -1)</int> + int cur = 0 模拟,比 STL 更贴近底层,但也更易越界:
立即学习“C++免费学习笔记(深入)”;
-
cur初始值必须是0,不能是未定义值或-1(-1 % m在 C++ 中仍是负数,越界) -
cur只在发生缺页且inMemory.size() == frameCount时才更新:cur = (cur + 1) % frameCount - 数组大小必须严格等于
frameCount;多一分可能覆盖相邻变量,少一分会导致cur越界写入 - 首次装入阶段(内存未满)绝不能动
cur,否则最早装入的页会被跳过淘汰
命中率分母为什么必须是总访问次数
缺页率 = pageFaults / pageReferences.size(),这个分母就是原始输入序列长度,一个都不能少。常见错误是把前 frameCount 次“填空闲帧”的访问过滤掉,或者对重复页号去重后再算。结果就是分子分母同时偏移,命中率失真且不可比。哪怕序列是 7 0 1 2 0 3 共 6 次访问,分母就是 6;第 1 次访 7、第 2 次访 0 全算缺页,计入分子——真实 OS 的 pagefault 计数器就是从第一次访存开始累加的。
真正容易被忽略的,是 cur 指针语义和 pageQueue.front() 安全调用这两处:前者常被误认为“当前最老页索引”,实际它是“下次该覆盖的位置”,最老页永远在 frames[cur];后者若不检查空队列,在 frameCount == 0 或空序列下直接触发未定义行为。


















