shared_ptr的原理
通过引用计数的方式来实现多个shared_ptr对象之间共享资源
例如:公司晚上会通知,最后走的员工把灯关掉
- shared_ptr在其内部,给每个资源都维护了着一份计数,用来记录该份资源被几个对象共享
- 在对象被销毁时(也就是析构函数调用),就说明自己不使用该资源了,对象的引用计数减1
- 如果引用计数是0,就说明自己是最后一个使用该资源的对象,必须释放该资源
- 如果不是0,就说明除了自己还有其他对象在使用该份资源,不能释放该资源,否则其他对象就成野指针了
#include <thread>
#include <mutex>
template <class T>
class SharedPtr {
public:
SharedPtr(T* ptr = nullptr)
: _ptr(ptr),
_pRefCount(new int(1)),
_pMutex(new mutex)
{
// 如果是一个空指针对象,则引用计数给0
if (_ptr == nullptr)
*_pRefCount = 0;
}
~SharedPtr() { Release(); }
SharedPtr(const SharedPtr<T>& sp)
: _ptr(sp._ptr),
_pRefCount(sp._pRefCount),
_pMutex(sp._pMutex)
{
// 如果是一个空指针对象,则不加引用计数,否则才加引用计数
if (_ptr)
AddRefCount();
}
// sp1 = sp2
SharedPtr<T>& operator=(const SharedPtr<T>& sp)
{
//if (this != &sp)
if (_ptr != sp._ptr)
{
// 释放管理的旧资源
Release();
// 共享管理新对象的资源,并增加引用计数
_ptr = sp._ptr;
_pRefCount = sp._pRefCount;
_pMutex = sp._pMutex;
if (_ptr)
AddRefCount();
}
return *this;
}
T& operator*() { return *_ptr; }
T* operator->() { return _ptr; }
int UseCount() { return *_pRefCount; }
T* Get() { return _ptr; }
int AddRefCount()
{
// 加锁或者使用加1的原子操作
_pMutex->lock();
++(*_pRefCount);
_pMutex->unlock();
return *_pRefCount;
}
int SubRefCount()
{
// 加锁或者使用减1的原子操作
_pMutex->lock();
--(*_pRefCount);
_pMutex->unlock();
return *_pRefCount;
}
private:
void Release() {
// 引用计数减1,如果减到0,则释放资源
if (_ptr && SubRefCount() == 0)
{
delete _ptr;
delete _pRefCount;
}
}
private:
int* _pRefCount;
// 引用计数
T* _ptr;
// 指向管理资源的指针
mutex* _pMutex;
// 互斥锁
};
本文详细解析了shared_ptr的工作原理,通过引用计数机制实现资源的共享与管理,避免了资源泄漏和野指针问题。文章提供了shared_ptr的实现代码,包括构造、析构、赋值操作符重载等关键部分,展示了如何在多线程环境下安全地增加和减少引用计数。
1745

被折叠的 条评论
为什么被折叠?



