不支持。C++20 中 std::atomic 仍未提供 std::shared_ptr 特化,因其非 trivially copyable;应使用标准提供的自由函数(如 std::atomic_load/store)配合 std::shared_ptr*,它们自动安全处理指针原子性与引用计数增减。

std::atomic<:shared_ptr>> 支持吗?
不支持。C++20 标准里 std::atomic 仍**不提供对 std::shared_ptr<t></t> 的特化**,所以你写 std::atomic<:shared_ptr>></:shared_ptr> 会编译失败(GCC/Clang 报错类似 static_assert failed: "std::atomic<t> requires T to be trivially copyable"</t>)。这是因为 std::shared_ptr 构造/析构涉及引用计数操作,不是 trivially copyable 类型。
那怎么原子地读写 shared_ptr?
用 std::atomic_load 和 std::atomic_store 配合裸指针 + 手动管理引用计数,或更安全地:用 std::atomic<:shared_ptr>></:shared_ptr> 的“模拟特化”——即 C++20 引入的 std::atomic<:shared_ptr>></:shared_ptr> **其实根本不存在**,但标准库提供了专用的自由函数:
std::atomic_load(const std::shared_ptr<t>* p)</t>std::atomic_store(std::shared_ptr<t>* p, std::shared_ptr<t> r)</t></t>std::atomic_exchange(std::shared_ptr<t>* p, std::shared_ptr<t> r)</t></t>std::atomic_compare_exchange_weak(std::shared_ptr<t>* p, std::shared_ptr<t>* expected, std::shared_ptr<t> desired)</t></t></t>
这些函数要求传入的是 std::shared_ptr<t>*</t>(裸指针),底层通过锁或 CAS 操作保证原子性,且**自动处理引用计数增减**——这才是正确用法。
常见错误:直接取地址再 cast 或用 std::atomic<void*>
有人试图绕过限制,比如:
立即学习“C++免费学习笔记(深入)”;
std::shared_ptr<int> ptr = std::make_shared<int>(42);
std::atomic<void*> raw{ptr.get()}; // ❌ 错!只原子了 raw 指针,没管引用计数
这会导致:ptr 析构时引用计数归零、对象被 delete,而 raw 还指向已释放内存;或者多个线程并发调用 get() 再存到 atomic<void></void>,完全丢失 shared_ptr 的所有权语义。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
必须用标准提供的自由函数,它们内部会:
- 在 store 时对新值做
shared_ptr拷贝(增加引用) - 在 load/exchange 时对旧值做析构(减少引用)
- 确保整个“读-改-写”过程对指针值和引用计数都一致
一个安全的多线程链表头更新示例
假设你要实现无锁栈的 head 原子更新:
struct Node {
int data;
std::shared_ptr<Node> next;
};
<p>std::shared_ptr<Node> head;</p><p>// 线程安全地 push
void push(int x) {
auto new_node = std::make_shared<Node>();
new_node->data = x;
new_node->next = head;
// 原子替换 head,同时保证 new_node 的引用计数+1、旧 head 的引用计数-1
std::atomic_store(&head, new_node);
}</p><p>// 线程安全地 pop
std::shared_ptr<Node> pop() {
std::shared_ptr<Node> curr = head;
std::shared_ptr<Node> next;
while (curr && !std::atomic_compare_exchange_weak(&head, &curr, curr->next)) {
// curr 已被更新为当前 head,继续尝试
next = curr->next;
}
return curr;
}
注意:&head 是 std::shared_ptr<node>*</node>,符合自由函数签名;std::atomic_compare_exchange_weak 会自动处理两次引用计数变更(失败时恢复 curr,成功时把旧 head 的引用减掉)。
真正容易被忽略的是:这些自由函数不是“语法糖”,它们是唯一能正确协调指针原子性和引用计数生命周期的机制。漏掉任何一个,就等于手动管理引用计数——而这恰恰是 shared_ptr 存在的理由。

















