统一 : 所有对外的创建接口都是增加一个引用计数; create!

 

提高点一:这里的关键是 Swap 方法会将当前对象的 ref_ 与临时对象 tmp 的 ref_(即 nullptr)交换,然后临时对象析构时释放原来的资源。 为啥释放原来的资源 如何理解?

我来解释一下这个资源释放的过程,这是理解智能指针工作机制的关键。

1. 赋值操作符的实现逻辑

当你执行 a = nullptr; 时,实际上调用了这个重载的赋值运算符:
void operator=(T* other) {
    SafePtr tmp(other);    // 创建临时对象 tmp,ref_ = nullptr
    Swap(tmp);             // 交换当前对象和 tmp 的 ref_
}                          // tmp 析构,调用 Release(),但 ref_ 为 nullptr,无操作
关键点在于 Swap(tmp) 这一步,我们需要深入理解它的作用。

2. Swap 方法的作用

Swap 方法的实现如下:
void Swap(SafePtr& other) {
    std::swap(ref_, other.ref_);
}
它的作用是交换当前对象(this)和传入对象(other)的内部指针 ref_

3. 资源释放的完整流程

让我们通过一个例子详细说明:
// 假设我们有一个已存在的 SafePtr 对象 a,它指向某个资源
SafePtr<MyClass> a(new MyClass());  // a.ref_ 指向 MyClass 对象

// 现在执行赋值操作
a = nullptr;
执行流程如下:

 

  1. 创建临时对象
    SafePtr tmp(nullptr);  // 调用 SafePtr(T* obj, bool isAddRef = true)
                           // tmp.ref_ 被设置为 nullptr,且不增加引用计数
    
  2. 交换指针
    Swap(tmp);  // 交换 a.ref_ 和 tmp.ref_
    
    • 交换前:a.ref_ 指向资源,tmp.ref_ 为 nullptr
    • 交换后:a.ref_ 变为 nullptrtmp.ref_ 指向原资源
  3. 临时对象析构
    ~SafePtr() {
        Release();
    }
    
    • tmp 离开作用域时调用析构函数
    • Release() 被调用,减少原资源的引用计数(如果引用计数变为 0,则释放资源

4. 为什么这样能安全释放资源?

这个机制的巧妙之处在于:
  • 资源所有权转移:通过 Swap,原资源的所有权被转移到临时对象 tmp
  • 自动释放:临时对象 tmp 是栈上对象,离开作用域时会自动调用析构函数
  • 引用计数管理Release() 方法确保引用计数正确减少,当计数为 0 时释放资源

5. 对比传统指针操作的风险

如果使用原始指针,这样的赋值操作会导致内存泄漏:
MyClass* ptr = new MyClass();
ptr = nullptr;  // 原资源泄漏!没有办法再 delete ptr
而 SafePtr 通过 RAII(资源获取即初始化)技术,确保资源在生命周期结束时自动释放。

总结

赋值为 nullptr 的过程可以概括为:
  1. 创建一个空的临时 SafePtr 对象
  2. 交换当前对象和临时对象的内部指针
  3. 临时对象析构时自动释放原资源

 

这种设计让资源管理变得安全,避免了手动管理内存的复杂性和风险。
Code
隐藏内容
本内容需权限查看
  • 普通用户: 0.1金币
  • VIP会员: 0.1金币
  • 永久会员: 0.1金币

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。