接上篇:share_ptr与weak_ptr的源码分析本篇主要介绍强弱指针计数器增减分析并模拟强弱指针。
C++新特性25,26_强弱指针计数器增减分析及模拟强弱指针
1. 关于强弱指针计数器增减分析
//强指针构造,析构,=赋值,拷贝构造等情况下 计数器的变化
//弱指针构造,析构,=赋值,拷贝构造等情况下 计数器的变化
//弱指针提升为强指针时 计数器的变化
//强指针直接构造(拿原始指针构造)时:
//1.初始化_Ty *_Ptr
//2.创建_Ref_count对象
//3._Ref_count_base对象构造时,会分别为_Uses=1并且_Weaks=1
1.1 初始化及增加的情形:
- 当创建一个新的shared_ptr时,内部对象计数器和自身的计数器均置1.
- 当将另外一个shared_ptr赋值给新的shared_ptr时,内部对象计数器+1,自身计数器不变。
- 当将另外一个shared_ptr赋值给新的weak_ptr时,内部对象计数器不变,自身计数器+1。
- 当从weak_ptr获取一个shared_ptr时,内部对象计数器+1,自身计数器不变。
1.2 减少的情形:
- 当一个shared_ptr析构时,内部对象计数器-1。当内部对象计数器减为0时,则释放内部对象,并将自身计数器-1。
- 当一个weak_ptr析构时,自身计数器-1。当自身计数器减为0时,则释放自身_Ref_count*对象。
1.3学习视频地址:强弱指针计数器增减分析
2. 模拟强弱指针
经过前面的分析,我们彻底理解了智能指针的使用,因此,这里我们根据stl中的智能指针的写法,对自己版本的智能指针进行修改,从而到底彻底理解智能指针的目的。
2.1模拟代码:
#include <memory>
#include <tchar.h>
class CRefCount
{
public:
CRefCount() {
m_nUsedCount = 1;
m_nWeakCount = 1;
}
void incUsed() {
m_nUsedCount++;
}
int decUsed() {
m_nUsedCount--;
return m_nUsedCount;
}
void incWeak() {
m_nWeakCount++;
}
int decWeak() {
m_nWeakCount--;
return m_nWeakCount;
}
int getUsed() {
return m_nUsedCount;
}
private:
int m_nUsedCount; //强指针引用次数
int m_nWeakCount; //弱指针引用次数
};
template<typename T>
class CMySmartPtrBase
{
public:
CMySmartPtrBase() {};
~CMySmartPtrBase() {};
void destroy() {
delete m_Ptr;
}
void release() {
if (m_pRef != nullptr && m_pRef->decWeak() == 0) {
delete m_pRef;
}
}
protected:
T* m_Ptr;
CRefCount* m_pRef;
};
//强指针类型
template<typename T>
class CMyWeakPtr;
template<typename T>
class CStrongPtr : public CMySmartPtrBase<T>
{
friend class CMyWeakPtr<T>;
public:
CStrongPtr() {
m_Ptr = nullptr;
m_pRef = nullptr;
}
explicit CStrongPtr(T* p) {
m_Ptr = p;
m_pRef = new CRefCount;
}
CStrongPtr(CStrongPtr<T>& obj) {
m_Ptr = obj.m_Ptr;
obj.m_pRef->incUsed();
m_pRef = obj.m_pRef;
}
CStrongPtr<T>& operator=(CStrongPtr<T>& obj) {
if (m_pRef != nullptr && m_pRef->decUsed() == 0) {
destroy();
release();
}
m_Ptr = obj.m_Ptr;
obj.m_pRef->incUsed();
m_pRef = obj.m_pRef;
return *this;
}
CStrongPtr(CMyWeakPtr<T>& obj) {
m_Ptr = obj.m_Ptr;
obj.m_pRef->incUsed();
m_pRef = obj.m_pRef;
}
~CStrongPtr() {
if (m_pRef != nullptr && m_pRef->decUsed() == 0) {
destroy();
release();
}
}
T& operator*() {
return *m_Ptr;
}
T* operator->() {
return m_Ptr;
}
T* get() {
return m_Ptr;
}
};
//强指针类型
template<typename T>
class CMyWeakPtr : public CMySmartPtrBase<T>
{
public:
friend class CStrongPtr<T>;
CMyWeakPtr() {
m_Ptr = nullptr;
m_pRef = nullptr;
}
CMyWeakPtr(CStrongPtr<T>& obj) {
//release();
m_Ptr = obj.m_Ptr;
obj.m_pRef->incWeak();
m_pRef = obj.m_pRef;
}
CMyWeakPtr<T>& operator = (CStrongPtr<T>& obj) {
release();
m_Ptr = obj.m_Ptr;
obj.m_pRef->incWeak();
m_pRef = obj.m_pRef;
return *this;
}
CMyWeakPtr(CMyWeakPtr<T>& obj) {
m_Ptr = obj.m_Ptr;
obj.m_pRef->incWeak();
m_pRef = obj.m_pRef;
}
~CMyWeakPtr() {
release();
}
CStrongPtr<T>& lock() {
if (m_pRef == nullptr) {
return CStrongPtr<T>();
}
return CStrongPtr<T>(*this);
}
bool IsExpried() {
if (m_pRef == nullptr) {
return true;
}
return m_pRef->getUsed() == 0;
}
};
class CSon;
class CTest {
public:
void set(CStrongPtr<CSon> p2) {
m_p1 = p2;
}
CStrongPtr<CSon> m_p1;
};
class CSon {
public:
void set(CStrongPtr<CTest> p2) {
m_p1 = p2;
}
CMyWeakPtr<CTest> m_p1;
};
void foo() {
CTest* father = new CTest();
CSon* son = new CSon();
CStrongPtr<CTest> ptrFather(father);
CStrongPtr<CSon> ptrSon(son);
father->set(ptrSon);
son->set(ptrFather);
}
int _tmain(int argc, _TCHAR* argv[])
{
foo();
return 0;
}
2.2 学习视频地址: 模拟强弱指针