无法用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
相关产品推荐
相关产品推荐

