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

无法用std::map::emplace插入无拷贝构造函数的类对象的问题

问题解答

1. 为什么需要拷贝构造函数?

你的分析方向是对的,错误核心源于MyClass无法被拷贝或移动,而当前emplace的调用方式触发了对拷贝构造函数的需求:

  • std::condition_variable是不可拷贝也不可移动的类型,因此包含它的MyClass会自动失去编译器生成的默认拷贝构造函数和移动构造函数。
  • 当你调用testmap.emplace("key", MyClass())时,传递的是一个临时MyClass对象作为参数,emplace会尝试构造std::pair<const std::string, MyClass>,需要将临时对象转移到pair的second成员中。
  • 由于MyClass没有可用的移动构造函数(成员m_cv不可移动),编译器会尝试回退到拷贝构造函数,但MyClass的拷贝构造函数也不可用,最终导致编译报错。

2. 如何改写代码以避免使用拷贝构造函数?

以下几种方案无需编写复杂的拷贝构造函数:

方案1:原地构造MyClass(推荐)

使用std::piecewise_construct配合std::forward_as_tuple,让emplace直接在map内存中构造MyClass,完全避免对象的拷贝/移动:

#include <map>
#include <condition_variable>
#include <tuple>

class MyClass
{
public:
    MyClass(): m_cv() {}
    std::condition_variable m_cv;
};

int main()
{
    std::map<std::string,MyClass> testmap;
    testmap.emplace(
        std::piecewise_construct,
        std::forward_as_tuple("key"),
        std::forward_as_tuple()
    );
}

方案2:使用try_emplace(C++17及以上)

C++17新增的try_emplace可以更简洁地实现原地构造,仅在键不存在时构造对象:

#include <map>
#include <condition_variable>

class MyClass
{
public:
    MyClass(): m_cv() {}
    std::condition_variable m_cv;
};

int main()
{
    std::map<std::string,MyClass> testmap;
    testmap.try_emplace("key");
}

方案3:存储对象指针

用std::unique_ptr存储MyClass的指针,map的value为指针类型,拷贝移动指针无需操作原对象:

#include <map>
#include <condition_variable>
#include <memory>

class MyClass
{
public:
    MyClass(): m_cv() {}
    std::condition_variable m_cv;
};

int main()
{
    std::map<std::string,std::unique_ptr<MyClass>> testmap;
    testmap.emplace("key", std::make_unique<MyClass>());
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 00:45:33