含map的自定义结构体用于std::atomic时默认构造函数被删除导致编译错误的咨询
先看你给出的代码:
struct debug_buf_list { int id; uint32_t *buf; }; struct debug_map_t { int b; std::map<uint32_t, struct debug_buf_list *> _debug_list; }; std::atomic<debug_map_t> debug_info;
编译时触发的错误:
error: the default constructor of "std::atomic<debug_map_t>" cannot be referenced -- it is a deleted function
错误原因
问题核心在于std::atomic对模板参数的类型限制。C++标准明确要求,std::atomic<T>的模板类型T必须是**可平凡复制(Trivially Copyable)**的类型——简单来说,这个类型不能包含像std::map这种带有复杂内部逻辑的非平凡成员。
std::map是一个动态容器,内部维护着堆内存,拥有自定义的构造、析构和复制逻辑,属于典型的非平凡类型。当你的debug_map_t包含std::map后,整个结构体就不再满足“可平凡复制”的要求。而std::atomic的默认构造函数只有在T符合条件时才会自动生成,否则会被标记为删除(deleted),这就是你看到编译报错的直接原因。
而当你移除std::map后,debug_map_t只剩基本类型int,属于可平凡复制范畴,所以std::atomic能正常生成默认构造函数,编译自然通过。
解决办法
std::atomic的设计初衷是对小体量、可平凡复制的类型(比如整数、指针)做原子操作,并不适合保护复杂容器。针对你的场景,有两种实用的解决思路:
1. 用互斥锁保护结构体的线程安全访问
这是最直接的方案,用std::mutex(如果需要读写分离可以用std::shared_mutex)包裹对debug_info的所有操作,确保多线程下的安全访问。示例代码如下:
#include <mutex> #include <map> #include <cstdint> struct debug_buf_list { int id; uint32_t *buf; }; struct debug_map_t { int b; std::map<uint32_t, debug_buf_list *> _debug_list; }; // 全局结构体实例 debug_map_t debug_info; // 对应的互斥锁 std::mutex debug_mutex; // 安全写入示例 void add_debug_buf(uint32_t index, debug_buf_list* buf) { std::lock_guard<std::mutex> lock(debug_mutex); debug_info._debug_list[index] = buf; } // 安全读取示例 debug_buf_list* get_debug_buf(uint32_t index) { std::lock_guard<std::mutex> lock(debug_mutex); auto it = debug_info._debug_list.find(index); return (it != debug_info._debug_list.end()) ? it->second : nullptr; }
std::lock_guard会自动管理锁的生命周期,避免手动加解锁时出现遗漏或死锁问题。
2. 拆分结构,分离原子操作与容器
如果你的场景中只有debug_map_t的部分成员需要原子操作,可以把这部分成员单独用std::atomic包裹,容器部分仍用互斥锁保护。比如:
struct debug_map_t { std::atomic<int> b; // 单独原子化需要原子操作的成员 std::map<uint32_t, debug_buf_list *> _debug_list; }; debug_map_t debug_info; std::mutex map_mutex; // 对b的原子操作无需锁 void update_b(int new_val) { debug_info.b.store(new_val, std::memory_order_relaxed); } // 对map的操作仍需锁保护 void add_to_map(uint32_t index, debug_buf_list* buf) { std::lock_guard<std::mutex> lock(map_mutex); debug_info._debug_list[index] = buf; }
这种方案适合需要对部分成员做轻量原子操作,同时对容器做线程安全访问的场景。
内容的提问来源于stack exchange,提问作者codeflow

