为何无法以类对象为参数创建C++11线程?
问题分析与解决方案
编译器报错根源
你的LRUCache类包含std::mutex和std::condition_variable成员,这两个类型不可拷贝、不可移动。创建线程时你用值传递c1,会触发LRUCache的拷贝构造,但因为类内存在不可拷贝成员,编译器自动生成的拷贝构造被禁用,因此报出无匹配构造函数的错误。
代码中的其他问题
get函数里mtx.unlock()写在return语句之后,永远不会执行,会导致锁无法释放,引发死锁。- main函数创建线程后未调用
t1.join()或t1.detach(),程序退出时线程仍在运行,会触发异常终止。 - 值传递缓存对象会让每个线程操作独立拷贝,完全失去多线程共享缓存的意义。
修改后的完整代码
#include <iostream> #include <unordered_map> #include <thread> #include <chrono> #include <mutex> using namespace std; class LRUCache { public: class Node { public: int key,val; Node* left,*right; Node(int _key,int _val):key(_key),val(_val),left(NULL),right(NULL) {} }*L,*R; unordered_map<int,Node*> m; int n; mutex mtx; condition_variable cv; void insert(Node* node) { Node* next=L->right; L->right=node; node->right=next; node->left=L; next->left=node; } void erase(Node* node) { node->left->right=node->right; node->right->left=node->left; } LRUCache(int capacity) { n=capacity; L=new Node(-1,-1),R=new Node(-1,-1); L->right=R; R->left=L; } // 显式禁用拷贝构造与赋值,避免意外拷贝 LRUCache(const LRUCache&) = delete; LRUCache& operator=(const LRUCache&) = delete; int get(int key) { if(m.count(key)==0) return -1; mtx.lock(); Node* node=m[key]; erase(node); insert(node); int val = node->val; // 先保存返回值,再解锁 mtx.unlock(); return val; } void put(int key, int value) { mtx.lock(); if(m.count(key)) { m[key]->val=value; erase(m[key]); insert(m[key]); } else { Node* node=new Node(key,value); if(m.size()==n) { Node* tmp=R->left; erase(tmp); m.erase(tmp->key); delete tmp; // 清理节点内存,避免泄漏 } insert(node); m[key]=node; } mtx.unlock(); } // 析构函数清理链表所有节点 ~LRUCache() { Node* cur = L; while(cur != nullptr) { Node* next = cur->right; delete cur; cur = next; } } }; // 用引用传递缓存,确保操作同一个实例 void putcache(LRUCache& c) { for(int i=1;i<=10;i++) { c.put(i,i+10); cout << "Put key: " << i << ", value: " << i+10 << endl; this_thread::sleep_for(std::chrono::seconds(1)); } } void getcache(LRUCache& c) { for(int i=1;i<=10;i++) { int val = c.get(i); cout << "Get key: " << i << ", value: " << val << endl; this_thread::sleep_for(std::chrono::seconds(1)); } } int main() { LRUCache c1(100); // 用std::ref传递引用,避免线程尝试拷贝对象 std::thread t1(putcache, std::ref(c1)); std::thread t2(getcache, std::ref(c1)); // 等待线程执行完成 t1.join(); t2.join(); return 0; }
核心修改点
- 将
putcache、getcache的参数改为LRUCache&,创建线程时用std::ref(c1)传递,确保多线程操作同一个缓存实例。 - 修正
get函数的解锁逻辑,先保存返回值再释放锁,避免死锁。 - 显式禁用
LRUCache的拷贝构造与赋值运算符,从根源杜绝拷贝问题。 - 添加析构函数清理链表节点,避免内存泄漏。
- 在main函数中调用
join()等待线程完成,防止程序异常终止。
内容的提问来源于stack exchange,提问作者Jacob
相关产品推荐
相关产品推荐

