如何将不可拷贝的LockWrap对象存入std::map?
解决无法将noncopyable派生类存入std::map的问题
你的问题核心在于:LockWrap继承自noncopyable(拷贝构造/赋值已被删除),且未定义移动构造/赋值函数,因此编译器不会生成默认的移动操作,导致std::map的常规插入/emplace操作(需要移动或拷贝元素)失败。以下是两种直接解决问题的方案:
方案一:原地构造元素(推荐,无需额外内存分配)
利用std::map::emplace结合std::piecewise_construct,直接在map的节点内存中构造LockWrap对象,完全避免移动或拷贝操作。修改main中的代码如下:
#include <tuple> // 需包含tuple头文件以使用piecewise_construct int main() { std::mutex mut; typedef std::map<int, LockWrap> map_type; map_type locks_held; int id = 1; // 原地构造LockWrap对象到map中 locks_held.emplace( std::piecewise_construct, std::forward_as_tuple(id), // 构造key的参数 std::forward_as_tuple(std::ref(mut)) // 构造LockWrap的参数(传递mutex引用) ); }
原理
std::piecewise_construct允许我们分别传递构造pair的两个元素(key和value)的参数,std::forward_as_tuple将参数打包成tuple,最终map会直接在自身内存空间中构造LockWrap对象,全程不涉及LockWrap的移动或拷贝操作。
方案二:使用智能指针包装
如果原地构造的方式不符合需求,可以用std::unique_ptr包装LockWrap,智能指针支持移动操作,且存储指针不需要拷贝LockWrap本身:
#include <memory> // 包含unique_ptr头文件 int main() { std::mutex mut; typedef std::map<int, std::unique_ptr<LockWrap>> map_type; map_type locks_held; int id = 1; // 存入包装后的智能指针 locks_held.emplace(id, std::make_unique<LockWrap>(mut)); }
原理
std::unique_ptr是可移动的,map中存储的是指针而非LockWrap对象本身,因此插入操作只需要移动智能指针,不会触发LockWrap的拷贝或移动逻辑。
内容的提问来源于stack exchange,提问作者calvin
相关产品推荐
相关产品推荐

