应同步维护驻留状态:一、用std::queue+std::unordered_set,队列管顺序、集合管存在性;二、手写循环数组模拟FIFO,严守下标更新条件;三、页号有限时可用std::vector替代哈希集以提升局部性。

如果您尝试用 C++ 实现 FIFO 页面置换算法并统计命中率,但结果出现缺页次数虚高、命中判断失效或淘汰错位,则很可能是由于仅依赖 std::queue 而未同步维护驻留状态所致。以下是解决此问题的步骤:
一、使用 std::queue + std::unordered_set 同步管理
该方法通过队列记录页面进入内存的顺序,哈希集合支持 O(1) 时间复杂度的驻留页存在性判断,二者操作严格对齐可避免误判缺页与重复装入。
1、声明两个核心结构:std::queue
2、初始化时确保 in_memory 为空,q 为空,pageFaults 计数器置零。
3、对每个访问页 page 执行判断:若 in_memory.find(page) != in_memory.end(),则为命中,不修改 q 且不增 pageFaults。
4、若未命中,则 pageFaults 加一;若 q.size() 等于物理块数 frame_count,则取 q.front() 为待淘汰页,执行 q.pop() 和 in_memory.erase(old)。
5、将新页 page 执行 q.push(page) 和 in_memory.insert(page)。
二、手写循环数组模拟 FIFO 队列
该方法规避 STL 分配开销,通过固定大小数组和下标 cur 管理逻辑队首,适用于对内存布局敏感或嵌入式环境下的模拟,需严守下标更新边界条件。
1、分配 int* frames = new int[frame_count],全部初始化为 -1(表示空闲)。
2、定义 int cur = 0,但仅在发生缺页且内存已满时才更新 cur = (cur + 1) % frame_count。
3、每次缺页时,先检查 frames[cur] 是否非 -1,若是则将其从驻留状态中移除(如用 bool in_mem[frame_count] 标记)。
4、将新页写入 frames[cur],并设置对应 in_mem 索引为 true。
5、首次装入阶段(内存未满)禁止移动 cur,否则最早装入页将无法被优先淘汰。
三、使用 std::vector 替代哈希集合标记驻留状态
当页面号范围有限且连续(如 0~99),可用布尔向量替代 unordered_set,节省哈希计算开销并提升缓存局部性,同时保持 O(1) 查找能力。
1、声明 std::vector
2、每次访问 page 前,直接检查 if (page
3、命中时不执行任何队列操作;缺页时,若内存已满,先将 frames[cur] 对应的 in_memory[old] 设为 false。
4、将新页 page 写入 frames[cur] 后,设 in_memory[page] = true。
5、必须确保 page 值不越界,否则 in_memory[page] 访问将导致未定义行为。
四、基于链表节点的手动 FIFO 管理
该方法显式构造双向链表节点,每个节点含 page_id 和前后指针,通过 head/tail 指针控制进出,便于调试淘汰路径与插入位置,适合教学演示场景。
1、定义 struct Node { int id; Node* next; Node* prev; }; 维护 head(最老)、tail(最新)指针。
2、命中时,将对应节点从原位置摘下,并重新链接至 tail 后(注意:FIFO 不需此步,但若后续扩展为 LRU 可复用)。
3、缺页且满时,从 head 摘下节点,释放内存,更新 head,并将新页构造成新节点插入 tail 后。
4、维护一个 std::unordered_map
5、每次 insert 或 erase 操作后必须校验 head 和 tail 的有效性,防止空指针解引用。
五、静态数组 + 线性探测查找驻留状态
该方法适用于极简环境或编译期确定页号范围的情形,用定长数组存储驻留页号,通过线性扫描完成存在性判断,虽时间复杂度为 O(m),但在小规模物理块(m ≤ 8)下性能可接受。
1、声明 int frames[8] = {-1}; int size = 0; int capacity = 8;
2、每次访问 page 前,遍历 frames[0] 至 frames[size-1],若发现匹配值则视为命中。
3、命中则跳过后续操作;缺页时,若 size
4、若 size == capacity,则 frames[0] 被淘汰,其余元素前移一位,frames[size-1] = page。
5、必须在每次淘汰后立即执行前移操作,否则 frames[0] 将持续保留旧值导致后续命中误判。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











