不能使用 std::map::emplace 插入没有复制构造函数的类的对象

Cannot use std::map::emplace to insert an object of a class with no copy constructor

提问人:Silverspur 提问时间:3/5/2023 最后编辑:HolyBlackCatSilverspur 更新时间:3/5/2023 访问量:183

问:

我正在尝试编译以下代码:

#include <map>
#include <condition_variable>

class MyClass
{
public:
    MyClass(): m_cv() {}
    std::condition_variable m_cv; //just to illustrate that a copy constructor is not obvious to write
};

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

编译在最后一行(方法调用)失败,并出现很长的错误,开始如下所示:emplace

error: no matching function for call to ‘std::pair, MyClass>::pair(const char [4], MyClass)

通过反复试验,我得出了这样的理解,即错误来自缺少 的复制构造函数。如果我添加一个,或者如果我用基本类型(例如)替换条件变量属性,错误就会消失。但是,我不确定我的分析,最重要的是,我不明白为什么这里需要复制构造函数。MyClassintMyClass

所以我的问题有两个方面:

  1. 为什么需要复制构造函数?
  2. 我怎样才能重写我的代码以不需要复制构造函数(由于类的复杂性,编写起来有点棘手,为了简洁起见,这里省略了)?
C++ C++14 复制构造函数 stdmap

评论

0赞 john 3/5/2023
我认为您需要提供一个 std::string 而不是字符串文字来放置。

答:

5赞 HolyBlackCat 3/5/2023 #1

在 C++ 17 中:

testmap.try_emplace("key");

在 C++ 14 或更早版本中:

testmap.emplace(std::piecewise_construct, std::forward_as_tuple("key"), std::tuple<>{});

你编码构造两次:一次是手动完成的(),第二次是在内部完成的(在你的例子中,它尝试调用复制构造函数)。MyClassMyClass()std::map

第二个构造函数调用不会消失,但您可以更改它接收的参数(如果有)。因此,您必须删除第一个调用,并将第二个调用更改为不接收任何参数,而不是 .const MyClass &

的参数直接指向 std::p air 的构造函数。如果您检查构造函数,则唯一可以默认构造第二个元素(不包括该对自己的默认构造函数)的构造函数似乎就是那个。.emplace()std::piecewise_construct

而 .try_emplace() 只是在内部使用。std::piecewise_construct