You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何无法以类对象为参数创建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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 03:20:31