#手写shared_ptr
Tree
shared_ptr
├── 构造函数
│ ├── shared_ptr(T* p = nullptr)
│
├── 拷贝构造函数
│ ├── shared_ptr(const shared_ptr<T>& other)
│
├── 赋值操作符
│ ├── shared_ptr<T>& operator=(const shared_ptr<T>& other)
│
├── 析构函数
│ ├── ~shared_ptr()
│
├── 释放资源函数
│ ├── void release()
│
├── 重置函数
│ ├── void reset(T* p = nullptr)
│
├── 获取原始指针函数
│ ├── T* get() const
│
├── 获取引用计数函数
│ ├── int use_count() const
│
├── 解引用操作符
│ ├── T& operator*() const
│
├── 箭头操作符
│ ├── T* operator->() const
│
代码实现
#include <iostream>
template <typename T>
class shared_ptr {
private:
T* ptr; // 原始指针
int* ref_count; // 引用计数
public:
// 构造函数
explicit shared_ptr(T* p = nullptr) : ptr(p), ref_count(new int(1)) {
if (ptr == nullptr) {
*ref_count = 0;
}
}
// 拷贝构造函数
shared_ptr(const shared_ptr<T>& other) : ptr(other.ptr), ref_count(other.ref_count) {
if (ptr) {
++(*ref_count);
}
}
// 赋值操作符
shared_ptr<T>& operator=(const shared_ptr<T>& other) {
if (this != &other) {
release();
ptr = other.ptr;
ref_count = other.ref_count;
if (ptr) {
++(*ref_count);
}
}
return *this;
}
// 析构函数
~shared_ptr() {
release();
}
// 释放资源
void release() {
if (ptr && --(*ref_count) == 0) {
delete ptr;
delete ref_count;
}
}
// 重置
void reset(T* p = nullptr) {
release();
ptr = p;
ref_count = new int(1);
if (ptr == nullptr) {
*ref_count = 0;
}
}
// 获取原始指针
T* get() const {
return ptr;
}
// 获取引用计数
int use_count() const {
return *ref_count;
}
// 重载解引用操作符
T& operator*() const {
return *ptr;
}
// 重载箭头操作符
T* operator->() const {
return ptr;
}
};
int main() {
shared_ptr<int> sp1(new int(10));
std::cout << "sp1 use_count: " << sp1.use_count() << std::endl;
{
shared_ptr<int> sp2 = sp1;
std::cout << "sp1 use_count after sp2: " << sp1.use_count() << std::endl;
std::cout << "sp2 use_count: " << sp2.use_count() << std::endl;
}
std::cout << "sp1 use_count after sp2 out of scope: " << sp1.use_count() << std::endl;
return 0;
}
输出
sp1 use_count: 1
sp1 use_count after sp2: 2
sp2 use_count: 2
sp1 use_count after sp2 out of scope: 1
构造函数
explicit shared_ptr(T* p = nullptr) : ptr(p), ref_count(new int(1)) {
if (ptr == nullptr) {
*ref_count = 0;
}
}
ptr
初始化为传入的指针p
。ref_count
初始化为一个新的整数,并设为1(初始引用计数)。- 如果
p
为nullptr
,则将引用计数设为0。
拷贝构造函数
shared_ptr(const shared_ptr<T>& other) : ptr(other.ptr), ref_count(other.ref_count) {
if (ptr) {
++(*ref_count);
}
}
- 将
ptr
和ref_count
拷贝自other
。 - 如果
ptr
非空,则增加引用计数。
赋值操作符
shared_ptr<T>& operator=(const shared_ptr<T>& other) {
if (this != &other) {
release(); // 释放当前持有的资源
ptr = other.ptr;
ref_count = other.ref_count;
if (ptr) {
++(*ref_count);
}
}
return *this;
}
- 先检查是否自我赋值,如果是则直接返回当前对象。
- 调用
release()
函数释放当前持有的资源。 - 拷贝
ptr
和ref_count
,并增加引用计数。
析构函数
~shared_ptr() {
release(); // 释放资源
}
- 调用
release()
函数释放资源。
释放资源
void release() {
if (ptr && --(*ref_count) == 0) {
delete ptr;
delete ref_count;
}
}
- 检查
ptr
是否非空,并减少引用计数。 - 如果引用计数为0,删除对象和引用计数器。
重置
void reset(T* p = nullptr) {
release(); // 释放当前持有的资源
ptr = p;
ref_count = new int(1);
if (ptr == nullptr) {
*ref_count = 0;
}
}
- 释放当前持有的资源。
- 将
ptr
设为新的指针p
,并重新初始化引用计数。
获取原始指针
T* get() const {
return ptr;
}
- 返回原始指针
ptr
。
获取引用计数
int use_count() const {
return *ref_count;
}
- 返回引用计数的值。
运算符重载
T& operator*() const {
return *ptr;
}
T* operator->() const {
return ptr;
}
- 提供解引用操作符
*
和箭头操作符->
,使shared_ptr
能像普通指针一样使用。
测试代码
int main() {
shared_ptr<int> sp1(new int(10));
std::cout << "sp1 use_count: " << sp1.use_count() << std::endl; // 输出1
{
shared_ptr<int> sp2 = sp1; // 拷贝构造
std::cout << "sp1 use_count after sp2: " << sp1.use_count() << std::endl; // 输出2
std::cout << "sp2 use_count: " << sp2.use_count() << std::endl; // 输出2
}
// sp2 离开作用域,引用计数减1
std::cout << "sp1 use_count after sp2 out of scope: " << sp1.use_count() << std::endl; // 输出1
return 0;
}
这个测试代码展示了 shared_ptr
如何管理引用计数。当 sp2
离开作用域时,它的析构函数被调用,引用计数减1,最终 sp1
的引用计数回到1。
P.S.