使用insert函数向std::map添加元素失败的排查与解决
修复std::map插入包含std::condition_variable的对象失败问题
问题原因
你的khaos_event类包含std::condition_variable成员,而std::condition_variable是不可拷贝的类型(它的拷贝构造函数被显式删除)。这导致khaos_event类的默认拷贝构造函数和拷贝赋值运算符被编译器自动禁用。
当你调用std::make_pair(1, khaos_event())时,需要创建std::pair<uint32_t, khaos_event>对象,这个过程会尝试拷贝临时的khaos_event实例,但因为拷贝构造函数不存在,最终触发编译错误。
修复方案
以下是几种可行的解决方式:
1. 使用std::map::emplace直接在容器内构造对象
emplace可以直接在map的内存空间中构造khaos_event对象,完全避免拷贝或移动操作:
int main() { std::map<uint32_t, khaos_event> events; events.emplace(1, khaos_event()); // 更简洁的写法:events.emplace(1, {}); ... }
2. 利用移动语义转移临时对象
std::condition_variable支持移动操作,编译器会为khaos_event自动生成默认的移动构造函数。可以用std::move将临时对象转移到pair中,避免拷贝:
int main() { std::map<uint32_t, khaos_event> events; events.insert(std::make_pair(1, std::move(khaos_event()))); // 也可以直接构造带移动语义的pair: // events.insert(std::pair<uint32_t, khaos_event>(1, std::move(khaos_event()))); ... }
3. 显式声明移动构造函数(可选)
如果后续给khaos_event添加了自定义的拷贝构造/赋值函数,编译器会停止自动生成移动构造,此时可以显式声明:
class khaos_event { public: khaos_event() = default; ~khaos_event() = default; // 显式声明默认移动构造和赋值 khaos_event(khaos_event&&) = default; khaos_event& operator=(khaos_event&&) = default; bool wait(uint32_t timeout){ std::chrono::milliseconds millis{timeout}; std::unique_lock<std::mutex> lock(m_mtx); return m_cv.wait_for(lock, millis) == std::cv_status::no_timeout; }; void notify(void){ std::unique_lock<std::mutex>lock(m_mtx); m_cv.notify_one(); }; private: std::condition_variable m_cv; std::mutex m_mtx; };
关键理解点
- 当类包含不可拷贝的成员时,类的拷贝操作会被编译器自动禁用,必须通过移动语义或直接在容器内构造的方式添加对象。
std::map::insert如果接收需要拷贝的对象,而对象不可拷贝时就会报错,改用emplace或移动操作可以绕过拷贝需求。
内容的提问来源于stack exchange,提问作者hyperion007
相关产品推荐
相关产品推荐

