1. SharedPointer的设计
(1)使用类模板,通过计数机制标识堆内存
(2)堆内存被指向时,(*refCount)++
(3)指针被置空时:(*refCount)—
(4)当*refCount == 0时,释放堆内存
2. 计数机制原理剖析
3. SharedPointer类的声明
template <typename T> class SharedPointer : public Pointer<T> { protected: int* m_refCount; //计数机制成员 public: SharedPointer(T* p = NULL); SharedPointer(const SharedPointer<T>& obj); SharedPointer<T>& operator=(const SharedPointer<T>& obj); void clear(); //将当前指针置为空 //由于SharedPointer支持多个对象同时指向一片堆空间 //因此必须支持比较操作! bool operator==(const SharedPointer<T>& obj); bool operator!=(const SharedPointer<T>& obj); ~SharedPointer(); };
4. 智能指针使用军规
(1)只能用来指向堆空间中的单个对象(变量)
(2)不同类型的智能指针对象不能混合使用
(3)不要使用delete释放智能指针指向的堆空间
【编程实验】SharedPointer智能指针的实现
//Pointer.h
#ifndef _POINTER_H_ #define _POINTER_H_ #include "Object.h" namespace DTLib { template <typename T> class Pointer : public Object //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 // _POINTER_H_
//SharedPointer.h
#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; void assign(const SharedPointer<T> &obj) { //复制 this->m_ref = obj.m_ref; this->m_pointer = obj.m_pointer; //指向后者的堆内存 if (this->m_ref) { //如果指向了合法的指针变量 (*this->m_ref)++; //计数加1 } } public: SharedPointer(T *p = NULL) : m_ref(NULL) { if (p) { //堆空间中申请4个字节的空间
//注意此处不用new,因为int是基本类型不是Object的子类,也就无法享受Object类中重载new的好处,即new int失败时,由于编译器处理方式不同,仍可能是NULL或抛异常。为了统一处理,用malloc
this->m_ref = static_cast<int*>(malloc(sizeof(int))); if (this->m_ref) { *(this->m_ref) = 1; //初始化1 ,说明p的堆空间已经有一个sharedpointer指针指向了 this->m_pointer = p; } else { //若malloc不成功,抛出异常 THROW_EXCEPTION(NotEnoughMemoryException, "No memory to create SharedPointer object ... "); } } } SharedPointer(const SharedPointer<T> &obj) : Pointer<T>(NULL) { //拷贝构造函数 assign(obj); } SharedPointer<T> &operator =(const SharedPointer<T> &obj) { if (this != &obj) { //避免自赋值 clear(); // 如果当前的sharepointer指针已经指向 另外一片堆空间, //应该先置空当前指针,不让它指向任何堆空间 assign(obj); } 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不为空指针 (*ref)--;//释放一个指针减1 if (*ref == 0) //若堆空间没有对应的指针指向 { free(ref); delete toDel; } } } //由于SharedPointer支持多个对象同时指向一片堆空间。因此必须支持比较操作! bool operator==(const SharedPointer<T>& obj) { return (this->m_pointer == obj.m_pointer); } bool operator!=(const SharedPointer<T>& obj) { return (this->m_pointer != obj.m_pointer); } ~SharedPointer() { clear(); } }; } #endif // _SHAREDPOINTER_H_
//main.cpp
#include <iostream> #include "SharedPointer.h" using namespace std; using namespace DTLib; class Test : public Object { public: int value; Test(): value(0) { cout << "Test()" << endl; } ~Test() { cout <<"~Test()" << endl; } }; int main() { //const SharedPointer<Test> sp0 = new Test(); SharedPointer<Test> sp0 = new Test(); SharedPointer<Test> sp1 = sp0; SharedPointer<Test> sp2 = NULL; sp2 = sp1; sp0->value = 100; cout << sp0->value << endl; cout << sp1->value << endl; cout << sp2->value << endl; //sp1.clear(); cout << (sp0==sp1) << endl; return 0; } /*输出结果 Test() 100 100 100 1 ~Test() */
5. 小结
(1)SharedPointer最大程度的模拟了原生指针的行为
(2)计数机制确保多个智能指针合法的指向同一片堆空间
(3)智能指针只能用于指向堆空间中的内存
(4)不同类型的智能指针不要混合使用
(5)堆对象的生命周期由智能指针进行管理