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

含std::thread成员的类存入std::vector触发已删除构造函数错误?

问题原因分析与解决

首先,核心问题出在C++的特殊成员函数生成规则上,结合std::thread的不可拷贝特性共同导致:

  • std::thread本身是不可拷贝、仅可移动的类型,所以当你的TEST类包含std::thread成员时,编译器会自动删除TEST的默认拷贝构造函数和拷贝赋值运算符——这部分你已经清楚。
  • 默认情况下,编译器会为TEST自动生成默认移动构造函数和默认移动赋值运算符,此时vector的插入操作(比如push_back、emplace_back)可以通过移动语义处理TEST对象,不会触发拷贝,所以单独使用类或者不显式定义析构时不会报错。

为什么显式定义析构函数会触发错误?

C++11及以后的标准规定:如果显式声明了析构函数、拷贝构造函数、拷贝赋值运算符中的任意一个,编译器就不会自动生成默认的移动构造函数和移动赋值运算符。

当你显式定义TEST的析构函数后,TEST同时失去了拷贝构造(被std::thread禁用)和移动构造(编译器不生成)的能力。而vector在插入元素或扩容时,需要将对象从一个内存位置转移到另一个位置——如果没有移动构造函数,编译器会退而求其次尝试调用拷贝构造函数,但拷贝构造已经被删除,于是触发C2280错误(引用已删除的函数)。

为什么emplace_back也会报错?

你可能以为emplace_back是直接在vector内存里构造对象,不会涉及拷贝/移动,但实际场景中:

  1. 如果vector当前容量不足以容纳新元素,会触发扩容操作:需要把旧内存中的所有元素转移到新分配的内存中,这时候就需要移动构造函数;
  2. 哪怕是第一次插入,如果你传递的是左值对象给emplace_back(比如emplace_back(test_obj)而非emplace_back(std::move(test_obj))),编译器仍会尝试调用拷贝构造,而拷贝已经被禁用,所以报错。

解决方案

显式让编译器为TEST生成移动构造和移动赋值运算符,或者手动实现它们:

class TEST {
public:
    std::thread t;

    // 自定义析构逻辑(如果需要)
    ~TEST() {
        if (t.joinable()) {
            t.join();
        }
    }

    // 让编译器生成默认移动构造和移动赋值
    TEST(TEST&&) = default;
    TEST& operator=(TEST&&) = default;
};

这样vector就可以通过移动语义处理TEST对象,不会再触发拷贝构造的错误。

内容的提问来源于stack exchange,提问作者Runsva

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 01:22:12