数据结构--另一种智能指针-SharedPointer
来源:互联网 发布:二次元网络漫画图片 编辑:程序博客网 时间:2024/05/29 02:50
上一篇讲了最多只能由一个指针标识堆空间的SmartPointer,本篇讲解另一种智能指针--SharedPointer。
设计要点:
使用类模板实现。
继承自Pointer类
通过计数机制(ref)标识堆空间:被指向时ref++;指向的指针被置空时ref--;当计数变量ref为0时堆空间应该被释放。所以计数变量和堆空间对象是绑定在一起。
由于SharedPointer支持多个对象同时指向一片堆空间,所以需要支持比较操作,所以需要实现比较操作符重载。
由于const对象会使用指针操作符,所以需要重载const版本的(->)和(*)操作符重载。
由于需要重载比较操作符,需要将Pointer类的get函数和isNull函数做成const成员函数。
SharedPointer类声明及完整实现:
template <typename T> class SharedPointer : public Pointer<T> { protected: int* m_ref;//计数变量 public: SharedPointer(T* p = NULL) : m_ref(NULL) { if(p) { this->m_ref = static_cast<int*>(malloc(sizeof(int))); if(this->m_ref) { (*this->m_ref) = 1;//申请空间成功后表示已经有指针指向它,计数变量加1。 this->m_pointer = p; } else//抛出异常 { THROW_EXCEPTION(NoEnoughMemoryException,"No enough memory to create..."); } } } SharedPointer(const SharedPointer<T>& obj):Pointer<T>(NULL)//拷贝构造,拷贝成功后计数变量加1 { this->m_ref = obj.m_ref; this->m_pointer = obj.m_pointer; if(this->m_ref) (*this->m_ref)++; } SharedPointer<T>& operator= (const SharedPointer<T>& obj)//赋值操作符重载,赋值成功后计数变量加1 { if(this != &obj) { clear();//清理当前指向 this->m_pointer = obj.m_pointer;//重新赋值 this->m_ref = obj.m_ref; (*this->m_ref)++; } return *this; } void clear()//清除当前对象指向的空间,当计数变量为0时释放堆空间和计数变量占用的空间 { 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(); } }; //比较操作符重载,作为全局重载函数 template <typename T> bool operator == (const SharedPointer<T>& l, const SharedPointer<T>& r) { return (l.get() == r.get()); } template <typename T> bool operator != (const SharedPointer<T>& l, const SharedPointer<T>& r)//const对象只能调用const成员函数 { return !(l == r); }
SharedPointer最大程度的模拟了原生指针的行为。
计数机制确保多个智能指针合法的指向同一片堆空间。
堆对象的生命周期由智能指针进行管理。
实现了自动管理内存。
使用军规:
只能用来指向堆空间中的单个变量或对象,不能是栈等内存。
不同类型的智能指针对象不能混合使用,SmartPointer对象和SharedPointer对象不能混合使用。
在使用智能指针后不要使用delete释放智能指针指向的堆空间。
测试代码:
class Test : public Object{public: int value; Test():value(0) { cout << "Test()" << endl; } Test(int value) { this->value = value; cout << "Test()" << endl; } ~Test() { cout << "~Test()" << endl; }};int main(){ SharedPointer<Test> sp = new Test(); SharedPointer<Test> nsp = NULL; nsp = sp; cout << sp->value << endl; cout << nsp->value << endl; nsp->value = 100; cout << sp->value << endl; cout << nsp->value << endl; cout << (sp == nsp) << endl; nsp.clear(); cout << (sp == nsp) << endl; cout << endl; const SharedPointer <Test> pp = new Test(111); //(pp->value) = 100;//const对象不能修改成员变量的值,可以加上mutable强制破除只读属性。 cout << pp->value << endl;
输出结果:
Test()
0
0
100
100
1
0
Test()
111
~Test()
~Test()
请自行对照结果分析原因。
小结:
这两篇内容重新设计了智能指针,使得智能指针在使用中更安全和方便。
阅读全文