std::atomic_shared_ptr 不是标准c++特性,已被否决,当前编译器均不支持;应使用 std::atomic 并链接 -latomic(gcc/clang),或改用互斥锁等更稳妥方案。

std::atomic_shared_ptr 是什么,现在能用吗
它不是标准 C++ 的正式特性,而是 C++20 中作为 std::atomic<:shared_ptr>></:shared_ptr> 的替代提案,在 TS(Technical Specification)中出现过,但最终被否决了。目前主流编译器(GCC、Clang、MSVC)**都不支持 std::atomic_shared_ptr 这个类型名**——你写上去会直接报错:error: 'atomic_shared_ptr' is not a member of 'std'。
真正可用的是 std::atomic<:shared_ptr>></:shared_ptr>,它从 C++20 起成为标准,但前提是你的 T* 必须是 trivially copyable(比如裸指针本身是,但 std::shared_ptr 内部结构是否可原子操作,取决于实现是否提供特化)。
常见错误现象:
- 写了
std::atomic_shared_ptr<int></int>,编译失败 - 写了
std::atomic<:shared_ptr>></:shared_ptr>,却在链接时报undefined reference to __atomic_load_16(尤其在 x86-64 上)
为什么 std::atomic<:shared_ptr>> 链接失败
因为 std::shared_ptr 通常 16 字节(控制块指针 + 管理对象指针),而 x86-64 默认不支持原生 16 字节原子操作,需要编译器生成库级原子调用(如 __atomic_load_16),这依赖 libatomic。
立即学习“C++免费学习笔记(深入)”;
实操建议:
- 用 GCC/Clang 编译时,必须加
-latomic链接选项(CMake 中:target_link_libraries(your_target atomic)) - MSVC 没这个问题,它用内建函数或锁回退,但性能略低
- 如果只在单核或确定无竞争场景用,其实没必要强上原子操作——
std::shared_ptr本身的引用计数已经是原子的,只是指针赋值不是
怎么安全地原子更新 shared_ptr 的指向
核心目标其实是:在多线程中无锁地替换一个 std::shared_ptr<t></t> 变量的值(比如配置热更新、状态切换)。正确做法是用 std::atomic<:shared_ptr>></:shared_ptr> + load()/store() 或 CAS。
示例(注意对齐和初始化):
std::atomic<std::shared_ptr<int>> ptr; ptr.store(std::make_shared<int>(42)); // OK auto p = ptr.load(); // OK ptr.exchange(std::make_shared<int>(100)); // OK
容易踩的坑:
- 不能直接
ptr = std::make_shared<int>(42)</int>—— 会调用隐式转换构造,但该构造非原子,必须显式用store() - 不要对
ptr.load()->value做长时操作,因为指针可能中途被其他线程替换成新对象,旧对象已析构 - 若 T 不是 trivially copyable(比如含虚函数、非 POD 类型),仍可工作,但原子操作本身只保证指针位模式的读写安全,不涉及 T 的构造/析构逻辑
有没有更轻量、更稳的替代方案
有。如果你只需要“原子地切换一个指针”,且不需要 shared_ptr 的共享语义,直接用 std::atomic<t></t> + 手动管理生命周期(比如配合 std::unique_ptr 或池化)更高效、更少陷阱。
或者用 std::shared_ptr 配合互斥锁(std::mutex),代码更直白、调试更友好,多数场景下性能差距远不如你想象的大。
真正复杂的地方在于:你以为你在解决并发指针更新问题,其实往往卡在内存序(memory order)选择、ABA 问题、或生命周期延长误判上——这些比选哪个原子类型难得多。










