C++实现LRU缓存时map解引用链表节点指针报错排查
LRU缓存编译错误分析与修正方案
嘿,其实编译错误的根源不是你标记的那行if (it == lmap.end()) return -1;——C++模板编译的错误提示经常会“错位”,真正的问题出在你对链表存储类型的定义上。让我给你拆解清楚:
1. 核心错误:模板参数误用
你写了:
list<vector<int, int>> kvList;
但std::vector的模板参数规则是std::vector<T, Allocator>,第二个参数必须是内存分配器类型(默认是std::allocator<T>),绝对不能是int。你想要存储[key, value]键值对,完全不需要用vector,直接用std::pair<int, int>就足够了,所以链表的正确类型应该是:
list<pair<int, int>> kvList;
编译器之所以把错误指向那行if语句,是因为它在实例化错误的vector<int, int>类型时,直到后续代码用到这个链表类型才触发完整的模板检查,导致错误提示“跑偏”了。
2. 原代码的其他逻辑问题
除了编译错误,你的LRU逻辑还有几个功能缺陷需要修正:
get方法里调用put(key, (*it->second)[0])是错误的:你传入的是键而非值,而且重复调用put会额外触发节点添加逻辑,不如直接把访问到的节点移到链表尾部(LRU的核心:最近使用的节点放尾部)put方法的节点操作顺序反了:应该先删除旧节点,再添加新节点- 缺失容量满时的淘汰逻辑:LRU需要在缓存达到最大容量时,删除最久未使用的节点(链表头部)
修正后的完整代码
#include <list> #include <unordered_map> #include <utility> class LRUCache { int maxCapacity; std::list<std::pair<int, int>> kvList; std::unordered_map<int, decltype(kvList)::iterator> lmap; public: LRUCache(int capacity): maxCapacity(capacity) {} int get(int key) { auto it = lmap.find(key); if (it == lmap.end()) return -1; // 将访问的节点移到链表尾部,标记为最近使用 kvList.splice(kvList.end(), kvList, it->second); return it->second->second; } void put(int key, int value) { auto it = lmap.find(key); if (it != lmap.end()) { // 存在旧节点则先删除 kvList.erase(it->second); } // 添加新节点到尾部 kvList.emplace_back(key, value); lmap[key] = std::prev(kvList.end()); // 容量超限,删除最久未使用的头部节点 if (lmap.size() > maxCapacity) { auto oldestNode = kvList.begin(); lmap.erase(oldestNode->first); kvList.erase(oldestNode); } } };
关键修正点说明
- 用
std::pair<int, int>替代错误的vector<int, int>,正确存储键值对 - 使用
list::splice高效移动节点到尾部,比删除再加新节点的性能更好 - 调整
put方法的操作顺序,避免冗余节点 - 添加容量超限的淘汰逻辑,符合LRU缓存的核心规则
内容的提问来源于stack exchange,提问作者Adrian
相关产品推荐
相关产品推荐

