当前位置: 首页 > news >正文

shared_ptr 源码解析

_Ptr_base

源码

template <class _Ty>
class _Ptr_base { // base class for shared_ptr and weak_ptr
public:using element_type = remove_extent_t<_Ty>;  //问题1 为什么使用remove_extent_t_NODISCARD long use_count() const noexcept {return _Rep ? _Rep->_Use_count() : 0;}template <class _Ty2>_NODISCARD bool owner_before(const _Ptr_base<_Ty2>& _Right) const noexcept { // compare addresses of manager objectsreturn _Rep < _Right._Rep;}_Ptr_base(const _Ptr_base&) = delete;_Ptr_base& operator=(const _Ptr_base&) = delete;protected:_NODISCARD element_type* get() const noexcept {return _Ptr;}constexpr _Ptr_base() noexcept = default;~_Ptr_base() = default;template <class _Ty2>void _Move_construct_from(_Ptr_base<_Ty2>&& _Right) noexcept {// implement shared_ptr's (converting) move ctor and weak_ptr's move ctor_Ptr = _Right._Ptr;_Rep = _Right._Rep;_Right._Ptr = nullptr;_Right._Rep = nullptr;}template <class _Ty2>void _Copy_construct_from(const shared_ptr<_Ty2>& _Other) noexcept {// implement shared_ptr's (converting) copy ctor_Other._Incref();_Ptr = _Other._Ptr;_Rep = _Other._Rep;}template <class _Ty2>void _Alias_construct_from(const shared_ptr<_Ty2>& _Other, element_type* _Px) noexcept {// implement shared_ptr's aliasing ctor_Other._Incref();_Ptr = _Px;_Rep = _Other._Rep;}template <class _Ty2>void _Alias_move_construct_from(shared_ptr<_Ty2>&& _Other, element_type* _Px) noexcept {// implement shared_ptr's aliasing move ctor_Ptr = _Px;_Rep = _Other._Rep;_Other._Ptr = nullptr;_Other._Rep = nullptr;}template <class _Ty0>friend class weak_ptr; // specifically, weak_ptr::lock()template <class _Ty2>bool _Construct_from_weak(const weak_ptr<_Ty2>& _Other) noexcept {// implement shared_ptr's ctor from weak_ptr, and weak_ptr::lock()if (_Other._Rep && _Other._Rep->_Incref_nz()) {_Ptr = _Other._Ptr;_Rep = _Other._Rep;return true;}return false;}void _Incref() const noexcept {if (_Rep) {_Rep->_Incref();}}void _Decref() noexcept { // decrement reference countif (_Rep) {_Rep->_Decref();}}void _Swap(_Ptr_base& _Right) noexcept { // swap pointers_STD swap(_Ptr, _Right._Ptr);_STD swap(_Rep, _Right._Rep);}template <class _Ty2>void _Weakly_construct_from(const _Ptr_base<_Ty2>& _Other) noexcept { // implement weak_ptr's ctorsif (_Other._Rep) {_Ptr = _Other._Ptr;_Rep = _Other._Rep;_Rep->_Incwref();} else {_STL_INTERNAL_CHECK(!_Ptr && !_Rep);}}template <class _Ty2>void _Weakly_convert_lvalue_avoiding_expired_conversions(const _Ptr_base<_Ty2>& _Other) noexcept {// implement weak_ptr's copy converting ctorif (_Other._Rep) {_Rep = _Other._Rep; // always share ownership_Rep->_Incwref();if (_Rep->_Incref_nz()) {_Ptr = _Other._Ptr; // keep resource alive during conversion, handling virtual inheritance_Rep->_Decref();} else {_STL_INTERNAL_CHECK(!_Ptr);}} else {_STL_INTERNAL_CHECK(!_Ptr && !_Rep);}}template <class _Ty2>void _Weakly_convert_rvalue_avoiding_expired_conversions(_Ptr_base<_Ty2>&& _Other) noexcept {// implement weak_ptr's move converting ctor_Rep        = _Other._Rep; // always transfer ownership_Other._Rep = nullptr;if (_Rep && _Rep->_Incref_nz()) {_Ptr = _Other._Ptr; // keep resource alive during conversion, handling virtual inheritance_Rep->_Decref();} else {_STL_INTERNAL_CHECK(!_Ptr);}_Other._Ptr = nullptr;}void _Incwref() const noexcept {if (_Rep) {_Rep->_Incwref();}}void _Decwref() noexcept { // decrement weak reference countif (_Rep) {_Rep->_Decwref();}}private:element_type* _Ptr{nullptr};_Ref_count_base* _Rep{nullptr};template <class _Ty0>friend class _Ptr_base;friend shared_ptr<_Ty>;template <class _Ty0>friend struct atomic;friend _Exception_ptr_access;#if _HAS_STATIC_RTTItemplate <class _Dx, class _Ty0>friend _Dx* get_deleter(const shared_ptr<_Ty0>& _Sx) noexcept;
#endif // _HAS_STATIC_RTTI
};

remove_extent_t原理和使用目的

template <class _Ty>
struct remove_extent { // remove array extentusing type = _Ty;
};template <class _Ty, size_t _Ix>
struct remove_extent<_Ty[_Ix]> {using type = _Ty;
};template <class _Ty>
struct remove_extent<_Ty[]> {using type = _Ty;
};template <class _Ty>
using remove_extent_t = typename remove_extent<_Ty>::type;
核心原因:统一处理数组和非数组类型
  • 目的:创建统一的元素类型表示

  • 效果

    • 对于非数组类型 Telement_type = T

    • 对于数组类型 T[N]T[]element_type = T

      element_type* _Ptr{nullptr};         // 实际存储的指针
      _Ref_count_base* _Rep{nullptr};      // 引用计数控制块
      
    • _Ptr 总是指向元素类型,而非整个数组类型

设计必要性分析
情况 1:数组类型处理
shared_ptr<int[]> arr(new int[5]);  // _Ty = int[]
  • remove_extent_t<int[]>int
  • _Ptr 类型为 int*(指向第一个元素)
  • 而非 int(*)[](指向整个数组)
情况 2:非数组类型处理
shared_ptr<Widget> w(new Widget);   // _Ty = Widget
  • remove_extent_t<Widget>Widget
  • _Ptr 类型为 Widget*
为什么需要这种设计
指针运算一致性
// 对数组类型进行指针运算
shared_ptr<int[]> arr(new int[5]);
int* first = arr.get();    // int*
int* second = first + 1;   // 合法指针运算// 如果 _Ptr 是 int(*)[] 类型:
int(*array_ptr)[] = arr.get();
// array_ptr + 1 将是未定义行为!
与标准库兼容
// 可与标准算法配合
shared_ptr<int[]> arr(new int[5]);
std::iota(arr.get(), arr.get() + 5, 0); // 需要元素指针类型
析构统一性
// 控制块中的删除器
template<typename T>
struct Ref_count {void destroy() {// 实际删除操作if constexpr (is_array_v<T>) {delete[] ptr;  // 需要元素类型指针} else {delete ptr;}}T* ptr; // 这里 T 是原始类型
};
类型系统一致性
// 用户期望的 get() 行为
shared_ptr<Widget[5]> w(new Widget[5]);
Widget* p = w.get(); // 而非 Widget(*)[5]// 实现:
element_type* get() const noexcept {return _Ptr; // 总是返回元素指针
}

为什么要删除基类拷贝和赋值构造

防止浅拷贝导致资源管理灾难

智能指针的核心职责是管理资源生命周期。如果允许基类拷贝:

_Ptr_base p1(/* 管理某个资源 */);
_Ptr_base p2 = p1; // 如果允许拷贝

会导致:

  • 两个对象共享同一个 _Rep(引用计数控制块)
  • 析构时双重释放资源
  • 引用计数管理混乱
强制子类实现正确的引用计数语义

不同子类需要不同的拷贝语义:

  • shared_ptr 拷贝:增加强引用计数
  • weak_ptr 拷贝:增加弱引用计数
  • 基类无法统一处理这些语义
避免意外切片(Slicing)

考虑以下危险场景:

void process_base(_Ptr_base<int> base) {// 如果允许拷贝,这里会复制基类部分// 导致引用计数错误
}shared_ptr<int> sp = make_shared<int>(42);
process_base(sp); // 切片拷贝!

_Ref_count_base

源码

class __declspec(novtable) _Ref_count_base { // common code for reference counting
private:
#ifdef _M_CEE_PURE// permanent workaround to avoid mentioning _purecall in msvcurt.lib, ptrustu.lib, or other support libsvirtual void _Destroy() noexcept {_STD terminate();}virtual void _Delete_this() noexcept {_STD terminate();}
#else // ^^^ _M_CEE_PURE / !_M_CEE_PURE vvvvirtual void _Destroy() noexcept     = 0; // destroy managed resourcevirtual void _Delete_this() noexcept = 0; // destroy self
#endif // _M_CEE_PURE_Atomic_counter_t _Uses  = 1;_Atomic_counter_t _Weaks = 1;protected:constexpr _Ref_count_base() noexcept = default; // non-atomic initializationspublic:_Ref_count_base(const _Ref_count_base&) = delete;_Ref_count_base& operator=(const _Ref_count_base&) = delete;virtual ~_Ref_count_base() noexcept {} // TRANSITION, should be non-virtualbool _Incref_nz() noexcept { // increment use count if not zero, return true if successful// 原子地增加引用计数(仅当计数非零时)auto& _Volatile_uses = reinterpret_cast<volatile long&>(_Uses);// 读取当前值(平台相关方式)
#ifdef _M_CEE_PURElong _Count = *_Atomic_address_as<const long>(&_Volatile_uses);
#else//`__iso_volatile_load32` 是一个编译器内置函数,用于安全地从 volatile 位置读取 32 位值(即使 `long` 在 Windows 上是 32 位)。这确保读取操作不会被编译器优化掉,并且会按顺序执行。long _Count = __iso_volatile_load32(reinterpret_cast<volatile int*>(&_Volatile_uses));
#endif// CAS(Compare-And-Swap) 循环while (_Count != 0) {const long _Old_value = _INTRIN_RELAXED(_InterlockedCompareExchange)(&_Volatile_uses, _Count + 1, _Count);if (_Old_value == _Count) {return true;}_Count = _Old_value;}return false;}void _Incref() noexcept { // increment use count_MT_INCR(_Uses);}void _Incwref() noexcept { // increment weak reference count_MT_INCR(_Weaks);}void _Decref() noexcept { // decrement use countif (_MT_DECR(_Uses) == 0) {_Destroy();_Decwref();}}void _Decwref() noexcept { // decrement weak reference countif (_MT_DECR(_Weaks) == 0) {_Delete_this();}}long _Use_count() const noexcept {return static_cast<long>(_Uses);}virtual void* _Get_deleter(const type_info&) const noexcept {return nullptr;}
};

_Incref_nz介绍

代码解析见源码

核心技术

内存模型选择:宽松内存序 (Relaxed Memory Order)
_INTRIN_RELAXED(_InterlockedCompareExchange)
  • 作用:使用 memory_order_relaxed 内存序
  • 优势
    • 避免不必要的内存屏障
    • 提升多核性能
  • 适用场景
    • 引用计数操作是"独立"的
    • 不需要保证操作顺序
    • 只需保证原子性
CAS (Compare-And-Swap) 循环
sequenceDiagramparticipant Thread as 当前线程participant Memory as 共享内存loop CAS循环Thread->>Memory: 读取当前值_Countalt _Count == 0Thread-->>Thread: 返回falseelseThread->>Memory: 尝试原子交换alt 交换成功Thread-->>Thread: 返回trueelseThread->>Thread: 更新_Count=旧值endendend
3. 平台兼容性处理
#ifdef _M_CEE_PURE// .NET 托管环境处理long _Count = *_Atomic_address_as<const long>(&_Volatile_uses);
#else// 原生环境处理long _Count = __iso_volatile_load32(...);
#endif
  • __iso_volatile_load32
    • MSVC 内部函数
    • 保证 volatile 读操作的原子性
    • 避免编译器优化重排
  • _Atomic_address_as
    • 用于 .NET 互操作环境
    • 桥接托管/非托管内存模型
4. Volatile 修饰符的双重作用
reinterpret_cast<volatile long&>(_Uses)
  • 硬件层面
    • 防止编译器缓存寄存器
    • 强制每次从内存读取
  • 编译器层面
    • 禁止指令重排序优化
    • 保证操作顺序性

设计必要性分析

解决弱引用提升的竞态条件
weak_ptr<T> wp = ...;
if (!wp.expired()) {// 此时可能已被其他线程释放shared_ptr<T> sp = wp.lock(); // 依赖_Incref_nz
}
确保对象存活性
成功
失败
弱引用调用lock
_Incref_nz
增加强引用计数
返回空shared_ptr
对象保持存活
对象已释放
性能优化考量
方法平均周期适用场景
互斥锁50-100ns复杂同步
CAS循环10-20ns简单原子操作
无锁队列20-40ns高竞争场景

_Ref_count

template <class _Ty>
class _Ref_count : public _Ref_count_base { // handle reference counting for pointer without deleter
public:explicit _Ref_count(_Ty* _Px) : _Ref_count_base(), _Ptr(_Px) {}private:virtual void _Destroy() noexcept override { // destroy managed resourcedelete _Ptr;}virtual void _Delete_this() noexcept override { // destroy selfdelete this;}_Ty* _Ptr;
};

构造函数

	template <class _Ux,enable_if_t<conjunction_v<conditional_t<is_array_v<_Ty>,_Can_array_delete<_Ux>,_Can_scalar_delete<_Ux>>,_SP_convertible<_Ux, _Ty>>,int> = 0>explicit shared_ptr(_Ux* _Px) { // construct shared_ptr object that owns _Pxif constexpr (is_array_v<_Ty>) {_Setpd(_Px, default_delete<_Ux[]>{});} else {_Temporary_owner<_Ux> _Owner(_Px);_Set_ptr_rep_and_enable_shared(_Owner._Ptr, new _Ref_count<_Ux>(_Owner._Ptr));_Owner._Ptr = nullptr;}}

参数介绍

  • _Ux:这是一个模板参数,表示传入的原始指针的类型。

  • enable_if_t<..., int> = 0:这是一个SFINAE(Substitution Failure Is Not An Error)约束,确保只有满足特定条件的类型_Ux才能使用这个构造函数。

  • 约束条件由conjunction_v(逻辑与)组合两个条件:

    1. conditional_t<is_array_v<_Ty>, _Can_array_delete<_Ux>, _Can_scalar_delete<_Ux>>:如果当前shared_ptr管理的类型_Ty是数组类型(is_array_v<_Ty>为真),则检查_Ux是否可以使用数组删除(即_Can_array_delete<_Ux>)。否则,检查_Ux是否可以使用标量删除(_Can_scalar_delete<_Ux>)。这是为了确保删除器是匹配的(数组用delete[],非数组用delete)。
    2. _SP_convertible<_Ux, _Ty>:检查_Ux*是否可以隐式转换为_Ty*。这确保了传入的指针类型与shared_ptr管理的类型兼容。
  • 如果这两个条件都满足,enable_if_t会得到一个类型int,并设置默认值为0,这样这个构造函数就可用。否则,这个构造函数会被从重载集中移除。

相关问题

构造函数为模版的原因
  • 在 C++ 的 shared_ptr 实现中,即使类模板已经定义为 shared_ptr<_Ty>,其构造函数为什么仍然使用成员函数模板(而不是普通函数)

  • 核心原因:支持多态和灵活构造

    • 多态指针支持

      // 需要允许从派生类指针构造基类指针
      class Base {};
      class Derived : public Base {};shared_ptr<Base> p(new Derived);  // 
      
    • 删除器类型擦除

      需要支持任意类型的删除器:
      // 普通函数无法处理不同类型的删除器
      void f() { auto deleter = [](FILE* p) { fclose(p); }shared_ptr<FILE> fp(fopen("a.txt", "r"), deleter); 
      }
      
SFINAE(Substitution Failure Is Not An Error)技术的工作原理
  • SFINAE 机制解析

    enable_if_t<Condition, int> = 0
    
    • enable_if_t 的本质

      template <bool _Test, class _Ty = void>
      struct enable_if {}; 			// no member "type" when !_Testtemplate <class _Ty>			// 特化:当条件为 true 时, 定义 type 类型
      struct enable_if<true, _Ty> { 	// type is _Ty for _Testusing type = _Ty;
      };template <bool _Test, class _Ty = void>
      using enable_if_t = typename enable_if<_Test, _Ty>::type;
      
      • 条件满足时(true)

        enable_if_t<true, int> → typename enable_if<true, int>::type → int
        

        此时模板实例化为:

        template <class _Ux, int = 0>
        explicit shared_ptr(_Ux* _Px);
        
      • 条件不满足时(false)

        enable_if_t<false, int> → typename enable_if<false, int>::type → (无定义!触发替换失败)
conjunction_v工作原理
  • 基础定义(空包情况)

    template <class... _Traits>
    struct conjunction : true_type {}; // If _Traits is empty, true_type
    
  • 递归处理(至少一个类型特征时)

    template <class _First, class... _Rest>
    struct conjunction<_First, _Rest...> : _Conjunction<_First::value, _First, _Rest...>::type {// the first false trait in _Traits, or the last trait if none are false
    };
    
  • _Conjunction 实现

    template <class _First, class... _Rest>
    struct conjunction<_First, _Rest...> : _Conjunction<_First::value, _First, _Rest...>::type {// the first false trait in _Traits, or the last trait if none are false
    };template <class _True, class _Next, class... _Rest>
    struct _Conjunction<true, _True, _Next, _Rest...> { // the first trait is true, try the next oneusing type = typename _Conjunction<_Next::value, _Next, _Rest...>::type;
    };
    
    • 所有特征为 true:返回最后一个特征的 type(继承自 true_type)。

    • 遇首个 false 特征:立即返回该特征(继承自 false_type),短路后续计算。

    • 空包:直接返回 true_type

  • 效果

    template <class... _Traits>
    _INLINE_VAR constexpr bool conjunction_v = conjunction<_Traits...>::value;
    
    • 返回条件选择后的trait的value
**conditional_t介绍 **
template <bool _Test, class _Ty1, class _Ty2>
struct conditional { // Choose _Ty1 if _Test is true, and _Ty2 otherwiseusing type = _Ty1;
};template <class _Ty1, class _Ty2>
struct conditional<false, _Ty1, _Ty2> {using type = _Ty2;
};template <bool _Test, class _Ty1, class _Ty2>
using conditional_t = typename conditional<_Test, _Ty1, _Ty2>::type;
is_array_v<_Ty> 介绍
template <class>
_INLINE_VAR constexpr bool is_array_v = false; // determine whether type argument is an arraytemplate <class _Ty, size_t _Nx>
_INLINE_VAR constexpr bool is_array_v<_Ty[_Nx]> = true;template <class _Ty>
_INLINE_VAR constexpr bool is_array_v<_Ty[]> = true;
  • 使用方式

    int arr[5];
    is_array_v<decltype(arr)> 
    

内部函数介绍

_Temporary_owner
template <class _Ux>
struct _Temporary_owner {_Ux* _Ptr;explicit _Temporary_owner(_Ux* const _Ptr_) noexcept : _Ptr(_Ptr_) {}_Temporary_owner(const _Temporary_owner&) = delete;_Temporary_owner& operator=(const _Temporary_owner&) = delete;~_Temporary_owner() {delete _Ptr;}
};// _Temporary_owner 是一个在 C++ 标准库中使用的辅助类,用于确保在构造函数中分配的资源在异常发生时能够被正确释放。它的主要目的是在构造函数中创建一个临时的资源管理对象,以确保即使在构造函数抛出异常的情况下,资源也能被正确释放,从而避免资源泄露。
_Set_ptr_rep_and_enable_shared
 template <class _Ux>void _Set_ptr_rep_and_enable_shared(_Ux* const _Px, _Ref_count_base* const _Rx) noexcept { // take ownership of _Pxthis->_Ptr = _Px;this->_Rep = _Rx;if constexpr (conjunction_v<negation<is_array<_Ty>>, negation<is_volatile<_Ux>>, _Can_enable_shared<_Ux>>) {if (_Px && _Px->_Wptr.expired()) {_Px->_Wptr = shared_ptr<remove_cv_t<_Ux>>(*this, const_cast<remove_cv_t<_Ux>*>(_Px));}}}void _Set_ptr_rep_and_enable_shared(nullptr_t, _Ref_count_base* const _Rx) noexcept { // take ownership of nullptrthis->_Ptr = nullptr;this->_Rep = _Rx;}

这个模板 _Can_enable_sharedstd::shared_ptr 实现中用于安全启用 std::enable_shared_from_this 功能的核心元编程组件.

核心目的是:

  • 验证类 _Yty 是否正确继承了 std::enable_shared_from_this,并确保可以通过安全的指针转换访问基类。这是实现 shared_from_this() 的关键前提。

相关文章:

  • 安卓vscodeAI开发实例
  • 【MySQL基础】MySQL内置函数全面解析:提升你的数据库操作效率
  • GVim-vimrc 字体缩放与界面优化配置
  • 一拖广角云台(一种广角镜头与云台相结合的监控设备)实现了动态追踪和预警功能
  • 开源ChatBI :深入解密 Spring AI Alibaba 的中文NL2SQL智能引擎
  • 门锁开关;与我们生活中紧密联系!
  • 前端vue js 使用插件 spark-md5 计算文件MD5值并封装成Promise异步调用方法
  • 小型语言模型(SLMs)有望重塑自主AI:效率、成本与实际部署
  • 深入探索 OpenCV 图像识别:从基础到深度学习
  • AI面试系统选型HR应考虑哪些问题?
  • JVM(7)——详解标记-整理算法
  • 安全工具:testssl.sh
  • 【鸿蒙HarmonyOS Next App实战开发】​​​​ArkUI纯色图生成器
  • 硬件-DAY04(ds18b20、ARM内核)
  • 回溯----8.N皇后
  • 日本生活:日语语言学校-日语作文-沟通无国界(3)-题目:わたしの友達
  • 深度学习-164-MCP技术之开发本地MCP服务器和异步客户端
  • JETBRAINS IDE 开发环境自定义设置快捷键
  • JMeter 高阶玩法:分布式压测的技术核心技术要点
  • 04、谁发明了深度学习的方法,是怎么发明的?
  • 网站建设一意见/推广如何做网上引流
  • 单页面推广网站/网页制作源代码
  • 网站logo设计标准/电商网站平台搭建
  • 网页制作q元素/网站推广优化公司
  • 工商营业执照查询网上查询/seo排名第一的企业
  • 做彩投网站犯法吗/怎么样建一个网站