std::shared_ptr引用计数线程安全及default_deleter空指针检查疑问
问题1解答
这个实现的引用计数操作不具备线程安全性,std::atomic<T*> 不会为指向的底层对象提供任何原子性保证。
std::atomic<int*>的原子保护范围仅覆盖指针变量自身存储的地址值:只有对这个指针变量本身的读、写、交换、地址偏移操作是原子的,完全不涉及指针指向地址上存储的实际数据。- 代码中
--(*reference_count)的执行逻辑分两步:第一步原子读取指针变量拿到引用计数的内存地址,第二步直接对这个地址上的普通int做非原子的自减操作。这一步没有任何原子保护,多线程下同时执行拷贝、析构操作时,会出现多个线程并发读写同一个普通int的情况,属于标准定义的数据竞争,会触发未定义行为。 - 标准库shared_ptr的正确实现中,引用计数本身就应当是原子类型,即使用
std::atomic<int>*存储计数指针,对计数的增减通过原子的fetch_add/fetch_sub接口完成,才能保证计数操作的线程安全。这份示例里的写法属于典型的实现错误,错把原子修饰放在了指针上,而非需要保护的计数值本身。
问题2解答
default_deleter中delete操作前的nullptr检查完全多余,没有存在的必要。
- C++标准明确规定,对空指针执行
delete是无任何副作用的安全操作,语言本身已经保证了这个行为,不需要手动加判断分支。 - 这类多余的空检查不仅没有实际收益,还会增加无意义的分支指令,甚至可能阻碍编译器的优化流程。
- 仅当你自定义了类的
operator delete重载,且重载实现没有兼容空指针入参的场景时,才需要额外做空指针判断,默认的全局delete永远不需要这类检查。
相关实现代码截图:
内容的提问来源于stack exchange,提问作者not_that_guy123
相关产品推荐
相关产品推荐


