C++含std::atomic<bool>成员的类无法插入std::unordered_map求助
问题原因与解决方案
核心原因
std::atomic<T>的拷贝构造函数和拷贝赋值运算符被显式删除——原子类型的拷贝会破坏其线程安全语义,因此标准库禁止了默认的拷贝操作。而std::unordered_map的insert、insert_or_assign等操作默认会尝试拷贝构造strategy对象,这直接导致编译失败。
可行解决方案
不需要移除std::atomic<bool>成员,以下是几种适配方案:
1. 利用移动语义(优先推荐)
std::atomic支持移动构造和移动赋值(C++11及以上标准),只要strategy类没有自定义拷贝构造/赋值运算符,编译器会自动生成合法的移动构造和移动赋值函数。此时可以通过右值引用或原地构造的方式向容器插入元素:
#include <unordered_map> #include <atomic> struct strategy { std::atomic<bool> flag{false}; // 其他成员... // 编译器自动生成移动构造/赋值,无需手动定义 }; struct strategyImpl { std::unordered_map<int, strategy> map; strategyImpl() { // 原地构造元素,完全避免拷贝 map.emplace(1, strategy{}); // 移动已有对象插入容器 strategy s; map.insert(std::pair<int, strategy>(2, std::move(s))); // insert_or_assign配合std::move使用 map.insert_or_assign(3, std::move(strategy{})); } };
2. 存储智能指针(适合需要保留原对象的场景)
如果必须保留strategy原对象的所有权,或者移动语义不符合业务逻辑,可以在容器中存储std::unique_ptr<strategy>或std::shared_ptr<strategy>。容器拷贝的是指针而非对象本身,不会触发std::atomic的拷贝操作:
#include <unordered_map> #include <atomic> #include <memory> struct strategy { std::atomic<bool> flag{false}; }; struct strategyImpl { std::unordered_map<int, std::unique_ptr<strategy>> map; strategyImpl() { // 插入智能指针包裹的对象 map.emplace(1, std::make_unique<strategy>()); map.insert_or_assign(2, std::make_unique<strategy>()); } };
3. 自定义拷贝逻辑(谨慎使用)
如果业务场景确实需要拷贝strategy对象,可以手动实现拷贝构造和赋值运算符,通过原子操作读取/写入std::atomic成员的值。注意:这种拷贝不是原子操作,可能存在线程安全风险,需结合业务场景评估可行性:
struct strategy { std::atomic<bool> flag{false}; // 自定义拷贝构造:原子读取原对象的flag值 strategy(const strategy& other) : flag(other.flag.load()) {} // 自定义拷贝赋值:原子读写保证值的一致性 strategy& operator=(const strategy& other) { if (this != &other) { flag.store(other.flag.load()); } return *this; } // 保留移动构造和赋值 strategy(strategy&&) = default; strategy& operator=(strategy&&) = default; };
内容的提问来源于stack exchange,提问作者Prabal Kajla
相关产品推荐
相关产品推荐

