FIFO页面置换需pageQueue与pageSet同步更新:查存在用unordered_set,取最老页用queue.front(),删页时二者必须同时操作;accessPage()须检查命中、满帧、队列非空;frameCount为0或1时有特殊边界行为。

FIFO 页面置换在 C++ 里不是靠手写队列就完事的,关键得让 pageQueue 和 pageSet 同步更新,漏一步就会缺页计数错、内存状态假。
为什么 queue + unordered_set 是最简可行组合
单用 queue 查不到“页面是否已在内存”,每次都要遍历——O(n) 查询拖垮整个模拟;单用 unordered_set 又没法知道谁“最早进来”。两者配对刚好:查存在用 pageSet.find(),取最老页用 pageQueue.front(),删老页后必须同步 pageSet.erase() 和 pageQueue.pop()。
常见错误现象:
- 只删
pageQueue没删pageSet→ 后续访问同一页仍判为缺页,但实际它还在内存里(逻辑矛盾) - 插入新页时只加
pageSet没推pageQueue→ 下次置换会拿错页(队列空或内容错乱)
accessPage() 函数里必须检查的三个条件
这个函数是 FIFO 模拟的核心入口,漏掉任一判断都会导致结果失真:
立即学习“C++免费学习笔记(深入)”;
- 先查
pageSet.find(pageNumber) != pageSet.end():命中直接返回,不碰队列也不增缺页 - 再判
pageSet.size() == frameCount:仅当满才置换,否则直接插入 - 置换前必须确保
!pageQueue.empty():避免空队列调用front()导致未定义行为(尤其在测试序列极短或 frameCount=0 时)
物理帧数 frameCount 为 0 或 1 时的边界行为
这不是理论假设,真实实验输入常出现这类值:
-
frameCount == 0:所有访问都缺页,pageSet始终为空,pageQueue永远不 push —— 必须在构造函数里加断言或日志提示,否则静默出错 -
frameCount == 1:每次新页都会挤掉上一页,pageQueue始终只有 1 个元素,pageSet大小恒为 1 —— 此时缺页次数等于不同页面数,可用来快速验证逻辑 - 若
frameCount > pageReferences.size():不会触发任何置换,缺页数 = 页面序列去重后的长度
输出内存快照时别直接打印 queue
queue 是单向的,无法遍历。想展示某次访问后的内存内容(比如 [1,2,3]),不能循环 pageQueue,而要维护一个独立的 vector<int></int> 或用辅助结构记录当前帧内页号顺序。否则你会看到“只能 front/pop,没法从头到尾读”的尴尬局面。
更现实的做法是:每次成功插入/置换后,把当前 pageSet 的内容 dump 到 vector 并排序(或按入队顺序重建),再输出——毕竟用户要的是“此刻内存里有哪几个页”,不是“队列底层怎么存的”。
真正容易被忽略的点:FIFO 的“先进先出”只体现在置换决策上,不保证内存中页面的显示顺序必须和入队顺序一致;但如果你的实验报告要求“按驻留时间从早到晚列出”,那就得额外保存入队时间戳或索引位置。


















