之前已经实现了一个智能指针类,为什么还要再论智能指针呢?
之前设计的SmartPointer的设计方案:
(1)指针生命周期结束时主动释放堆空间;
(2)一片堆空间最多只能由一个指针标识;
(3)杜绝指针运算和指针比较。
思考:
如何实现 SharedPointer 使得多个智能指针对象可以指向同一片堆内存 , 同时支持堆内存的自动释放?
设计思路:
Pointer继承自Object,只要不实现析构函数,那么Pointer这个类就是一个抽象类。实现方式:
#ifndef _POINTER_H_
#define _POINTER_H_
#include "Object.h"
namespace DTLib
{
template < typename T >
class Pointer : public Object
{
protected:
T* m_pointer;
public:
Pointer(T* p = NULL)
{
m_pointer = p;
}
T* operator-> ()
{
return m_pointer;
}
T& operator* ()
{
return *m_pointer;
}
const T* operator-> () const
{
return m_pointer;
}
const T& operator* () const
{
return *m_pointer;
}
bool isNull() const
{
return (m_pointer == NULL);
}
T* get() const
{
return m_pointer;
}
};
}
#endif
重新实现SmartPointer:
#ifndef _SMARTPOINTER_H_
#define _SMARTPOINTER_H_
#include "Pointer.h"
namespace DTLib
{
template <typename T>
class SmartPointer : public Pointer<T>
{
public:
SmartPointer(T* p = NULL) : Pointer<T>(p)
{
}
SmartPointer(const SmartPointer<T>& obj) : Pointer<T>(obj)
{
this->m_pointer = obj.m_pointer;
const_cast<SmartPointer<T>&>(obj).m_pointer = NULL;
}
SmartPointer<T>& operator = (const SmartPointer<T>& obj)
{
if (this != &obj)
{
T* p = this->m_pointer; // 要保证异常安全
this->m_pointer = obj.m_pointer;
const_cast<SmartPointer<T>&>(obj).m_pointer = NULL;
delete p; // 保证异常安全
}
return *this;
}
~SmartPointer()
{
delete this->m_pointer;
}
};
}
#endif
SharedPointer的设计要点:
通过计数机制ref标识堆内存:
1、堆内存被指向时 : ref++;
2、指针被置空时 :ref –;
3、ref==0时 :释放堆内存。
代码实现:
(1)实现拷贝构造时,自身的m_ref要挂接到被拷贝的对象上去;
(2)实现赋值操作时,说明不再指向原来的堆空间,自身的m_ref要减减,为空时要释放指针指向的空间和计数机制的空间;
(3)析构函数里要调用clear函数实现堆空间内存自动释放。
核心是下面的clear函数的实现,同时要注意保证程序的异常安全。
#ifndef _SHAREDPOINTER_H_
#define _SHAREDPOINTER_H_
#include "Pointer.h"
#include "Exception.h"
#include <cstdlib>
namespace DTLib
{
template < typename T >
class SharedPointer : public Pointer<T>
{
protected:
int* m_ref; // 计数机制贯穿SharedPointer类实现的全过程,实现的时候要主要这些细节。
public:
SharedPointer(T* p = NULL) : m_ref(NULL)
{
if (p)
{
this->m_ref = static_cast<int*>(std::malloc(sizeof(int)));
if (this->m_ref)
{
(*m_ref) = 1;
this->m_pointer = p;
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException, "No memery to create SharedPointer object ...");
}
}
}
SharedPointer(const SharedPointer<T>& obj) : Pointer<T>(NULL)
{
this->m_ref = obj.m_ref; // 自身的m_ref要挂接到被拷贝的对象上去
this->m_pointer = obj.m_pointer;
if (this->m_ref)
{
(*this->m_ref)++;
}
}
SharedPointer<T>& operator= (const SharedPointer<T>& obj)
{
if (this != &obj)
{
clear();
this->m_ref = obj.m_ref;
this->m_pointer = obj.m_pointer;
if (this->m_ref)
{
(*this->m_ref)++;
}
}
return *this;
}
void clear()
{
T* toDel = this->m_pointer;
int* ref = this->m_ref;
this->m_pointer = NULL;
this->m_ref = NULL;
if (ref)
{
(*ref)--;
if ((*ref) == 0)
{
free(ref);
delete toDel;
}
}
}
~SharedPointer()
{
clear();
}
};
}
#endif
小结:
(1)SharedPointer最大程度的模拟了原生指针的行为;
(2)计数机制确保多个智能指针合法的指向同一片堆空间;
(3)智能指针只能用于指向堆空间中的内存;
(4)不同类型的智能指针不要混合使用;
(5)堆对象的生命周期由智能指针进行管理。