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

Sil*_*pur 2 c++ stdmap copy-constructor c++14

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

\n
#include <map>\n#include <condition_variable>\n\nclass MyClass\n{\npublic:\n    MyClass(): m_cv() {}\n    std::condition_variable m_cv; //just to illustrate that a copy constructor is not obvious to write\n};\n\nint main()\n{\n    std::map<std::string,MyClass> testmap;\n    testmap.emplace("key",MyClass());\n}\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
error: no matching function for call to \xe2\x80\x98std::pair, MyClass>::pair(const char [4], MyClass)\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

所以我的问题是双重的:

\n
    \n
  1. 为什么需要复制构造函数?
  2. \n
  3. 如何重写我的代码以便不需要复制构造函数(由于类的复杂性,编写起来有点棘手,为简洁起见,此处省略)?
  4. \n
\n

Hol*_*Cat 5

在 C++17 中:

testmap.try_emplace("key");
Run Code Online (Sandbox Code Playgroud)

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

testmap.emplace(std::piecewise_construct, std::forward_as_tuple("key"), std::tuple<>{});
Run Code Online (Sandbox Code Playgroud)

您编写两次构造代码MyClass:一次手动执行(MyClass()),第二次std::map在内部执行(在您的情况下,它尝试调用复制构造函数)。

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

的参数.emplace()直接进入 的构造函数std::pair。如果您检查构造函数,您会发现唯一一个可以默认构造第二个元素(不包括该对自己的默认构造函数)的似乎就是这个std::piecewise_construct

并且.try_emplace()只是内部使用std::piecewise_construct