实现自定义智能指针需通过模板和引用计数控制对象生命周期。首先定义RefCountBlock管理指针和引用计数,构造时初始化计数为1,析构时删除对象;再实现SharedPtr模板类,封装控制块指针和原始指针,拷贝时增加引用计数,赋值前处理自赋值并释放旧资源,析构时调用release递减计数,归零则删除控制块;为支持继承体系,添加跨类型构造函数,允许SharedPtr转为SharedPtr;测试示例验证构造、析构顺序及引用计数变化,确保无内存泄漏。最终实现一个基础的引用计数型智能指针。
实现自定义智能指针并加入引用计数机制,核心在于管理对象生命周期,避免内存泄漏和重复释放。通过模板技术,可以让智能指针支持任意类型,提升通用性。下面详细介绍如何一步步开发一个简单的引用计数型智能指针模板。
设计引用计数控制块
为了实现共享所有权,需要一个独立的控制块来保存引用计数和指向实际对象的指针。这个控制块由所有指向同一对象的智能指针共享。
控制块通常包含:
- 指向管理对象的指针
- 当前强引用的数量(决定对象何时释放)
- 析构时清理资源的逻辑
示例代码结构:
template<typename T> class RefCountBlock { public: T* ptr; int ref_count; <pre class="brush:php;toolbar:false"><pre class="brush:php;toolbar:false">RefCountBlock(T* p) : ptr(p), ref_count(1) {} ~RefCountBlock() { delete ptr; }
};
实现智能指针模板类
定义一个模板类 SharedPtr,封装对控制块和对象的访问。构造、拷贝、赋值和析构操作都需要更新引用计数。
关键操作包括:
- 构造时创建控制块或绑定已有块
- 拷贝构造时增加引用计数
- 赋值操作需处理自赋值和旧资源释放
- 析构时减少计数,归零则删除对象
基本框架:
template<typename T> class SharedPtr { private: T* ptr; RefCountBlock<T>* block; <pre class="brush:php;toolbar:false"><pre class="brush:php;toolbar:false">void release() { if (block && --block->ref_count == 0) { delete block; } ptr = nullptr; block = nullptr; }
public: explicit SharedPtr(T* p = nullptr) : ptr(p), block(p ? new RefCountBlock
SharedPtr(const SharedPtr& other) : ptr(other.ptr), block(other.block) { if (block) ++block->ref_count; } SharedPtr& operator=(const SharedPtr& other) { if (this != &other) { release(); ptr = other.ptr; block = other.block; if (block) ++block->ref_count; } return *this; } ~SharedPtr() { release(); } T& operator*() const { return *ptr; } T* operator->() const { return ptr; } int use_count() const { return block ? block->ref_count : 0; } explicit operator bool() const { return ptr != nullptr; }
};
支持模板类型推导与赋值兼容性
为了让智能指针支持继承关系的指针赋值(如子类转父类),需要添加模板构造和赋值函数。
例如,允许 SharedPtr
添加泛化构造函数:
template<typename U> SharedPtr(const SharedPtr<U>& other) : ptr(other.ptr), block(other.block) { if (block) ++block->ref_count; }
注意:需确保类型转换安全,可通过 static_cast 或 dynamic_cast 控制转换逻辑。
测试与使用示例
验证智能指针是否正确管理生命周期。
#include <iostream> struct Test { Test() { std::cout << "Test()n"; } ~Test() { std::cout << "~Test()n"; } }; <p>int main() { { SharedPtr<Test> p1(new Test); std::cout << "ref count: " << p1.use_count() << "n";</p><pre class="brush:php;toolbar:false"><pre class="brush:php;toolbar:false"> { SharedPtr<Test> p2 = p1; std::cout << "ref count: " << p1.use_count() << "n"; } std::cout << "p2 out of scopen"; } // p1 析构,对象释放 return 0;
}
输出应显示构造一次、析构一次,引用计数正确增减。
基本上就这些。通过封装控制块和正确管理引用计数,就能实现一个基础但实用的引用计数智能指针模板。后续可扩展支持弱引用、自定义删除器等功能。
评论(已关闭)
评论已关闭