#手写shared_ptr
#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; // 输出2std::cout << "sp2 use_count: " << sp2.use_count() << std::endl; // 输出2}// sp2 离开作用域,引用计数减1std::cout << "sp1 use_count after sp2 out of scope: " << sp1.use_count() << std::endl; // 输出1return 0;
}
这个测试代码展示了 shared_ptr
如何管理引用计数。当 sp2
离开作用域时,它的析构函数被调用,引用计数减1,最终 sp1
的引用计数回到1。
P.S.