std::shared_ptr 本身不支持延迟初始化,必须手动封装
标准库的 std::shared_ptr 是一个裸指针包装器,构造时就完成资源获取(如调用 new 或工厂函数),它不内置“首次访问才创建”的逻辑。所谓“延迟初始化”,本质是业务逻辑层的责任,不是智能指针的职责。
常见误用是试图在多线程中直接对 std::shared_ptr 成员变量做“判空 + 构造”操作,这会引发竞态——两个线程同时看到空指针、同时执行 new,导致资源重复创建或泄漏。
正确做法是把延迟逻辑抽出来,配合同步机制(如 std::call_once 或互斥锁)控制初始化时机。
用 std::call_once 实现线程安全的延迟初始化(推荐)
std::call_once 是 C++11 提供的轻量级一次性初始化原语,比手写双重检查锁(DCLP)更简洁、更不易出错,且无内存序陷阱。
立即学习“C++免费学习笔记(深入)”;
- 它内部已处理了内存屏障和原子状态,无需手动写
std::atomic或std::memory_order - 初始化函数只执行一次,即使多个线程同时进入,也只有一个成功执行,其余阻塞等待完成
- 配合
std::shared_ptr的线程安全赋值(operator=对shared_ptr对象本身是线程安全的),可安全发布共享对象
示例: