不能直接用 std::queue 模拟 FIFO 页面置换,因为它不支持 O(1) 查找,无法快速判断页是否在内存中,导致命中判断失效、缺页统计错误;必须配合 std::unordered_set 和循环数组等结构协同维护。

不能直接用 std::queue 模拟 FIFO 页面置换——它只管顺序,不管“页在不在内存里”,命中判断会失效,缺页统计必然出错。
为什么 std::queue 单独用不了?
页面置换不是单纯记录“谁先来”,而是每次访问都要快速回答:“这个页号当前是否已在物理块中?”
-
std::queue不支持 O(1) 查找:必须遍历整个队列才能确认是否存在,当物理块数m达到 64、访问序列长度n达到 10000 时,查找开销从 O(1) 退化为 O(m),整体变成 O(n·m) - 即使你用
std::queue存页面号,也得同步维护一个std::unordered_set<int></int>记录驻留页;否则第二次访问同一页面时,程序仍会当作缺页处理 - 淘汰后若没从
unordered_set中删掉旧页号,后续再次访问该页会被误判为“不在内存”,造成重复装入和虚高缺页数
循环数组 + cur 指针的边界陷阱
手写 FIFO 常用循环数组模拟队列头,靠 cur = (cur + 1) % m 移动。但这个操作只在缺页且内存已满时才应执行。
- 命中时不更新
cur:如果每次访问都无条件移动cur,下次淘汰位置就偏了,实际淘汰的可能是刚命中的页 -
cur初始化必须为 0(或明确赋值),不能是未定义值或 -1;C++11 后-1 % m是 -1,不是m-1,会导致越界写入 - 数组大小必须严格等于物理块数
m,不能用固定大数组(如int page[100])只填前m个——cur越界后可能覆盖相邻变量,引发静默错误
缺页率计算的分母必须是总访问次数
分子是缺页发生次数,分母就是原始页面访问序列的长度 n,不剔除任何访问,也不去重。
- 示例序列
{7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1}共 17 个元素 → 分母固定为 17 - 第 1 次访问 0 → 缺页(计入分子);第 5 次再访 0 → 命中(不计入分子,但计入分母)
- 常见错误:把内存填满前的几次访问跳过计数,或把“首次装入”和“命中”混为一谈,导致缺页率偏低失真
推荐最小可行结构组合
用三个独立但同步更新的部件构成闭环逻辑:
- 一个
std::vector<int></int>或原生数组int frame[m]存当前驻留页号(按 FIFO 顺序排列) - 一个
std::unordered_set<int></int>快速查页是否在内存中(O(1) 平均) - 一个整型变量
cur,仅在缺页且size() == m时更新:cur = (cur + 1) % m
三者更新必须原子同步:装入新页时,要往 frame[cur] 写值、往 unordered_set 插入页号、并(条件触发)更新 cur;淘汰旧页时,必须从 unordered_set 中 erase 对应旧页号。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











