9.13 C和C++ 13.8编写一个智能指针类

来源:互联网 发布:mac 最好的五笔输入法 编辑:程序博客网 时间:2024/06/08 13:37
#include <iostream>#include <stdio.h>using namespace std;/*问题:编写一个智能指针类。智能指针是一种数据类型,一般用模板实现,模拟指针行为,同时还提供自动垃圾回收机制。它会自动记录SmartPointer<T*>对象的      引用计数,一旦T类对象的引用计数为零,就会释放该对象。分析:最为关键的是:1智能指针能被原始指针初始化,2实现引用计数,所谓引用计数,一旦有地方使用,就加1,一旦使用结束就减少计数。      关键计数功能,还是不明白引用计数到底怎么实现的。关键:1 书上解法:1)引用计数不能用整数,用unsigned的指针,大家全局共享计数(后续副本直接复制,不需要分配内存),指针可以在拷贝的时候通过深拷贝          2)构造函数中,引用计数要初始化为1,因为构造表示使用  3)拷贝构造函数中,直接把原始指针和引用计数复制给新的,累加计数【之所以累加计数,是因为你拷贝了相当于多了一个地方使用】  4)析构函数中,先减少引用计数,若变为0,就释放原始指针【我漏了不为0的时候要减少计数】  5)赋值函数将ptr1赋值给ptr2,需要减少ptr1的引用计数【?】,创建新引用,累加计数【?】*///注意是模板,不是 类型名称template<class T>class SmartPointer{public://构造函数,使得引用计数为1,否则一直为0,直接就析构了,这里引用计数器注意是指针【?】SmartPointer(T* obj){_obj = obj;//引用计数器需要用malloc分配内存,这里sizeof就对应一个unsigned *长度_refCount = (unsigned*) malloc(sizeof(unsigned*));*_refCount = 1;}//析构的时候,如果引用计数为0,就删除指针【错】,这样存在不会引用计数减1的情况,应该先直接减少计数,再判断是否需要删除对象~SmartPointer(){remove();}//拷贝构造函数,这里无需自己构建一个,因为当前拷贝就是构建,你只需要复制就可以SmartPointer(SmartPointer<T>& sptr){//先创建原始指针对象和引用计数,原始指针对象是要重新分配内存,引用计数作为全局共享不分配内存_obj = sptr._obj;_refCount = sptr._refCount;//下面是累加当前的引用计数,果然是直接复制 引用计数器,因为全局共享一份++(*_refCount);}//赋值符号重载,返回的仍然是引用,注意不要丢失"&"//将旧的只能指针复制给另一个指针,旧的(A = B中的A)计数减一,新的引用计数加1;之所以旧的减1是因为旧的对象被换成新的对象,自然要减一SmartPointer<T>& operator = (SmartPointer<T>& sptr){//如果当前对象已经等于赋值对象,直接返回if(this == &sptr){return *this;}//检查当前对象是否超过0,说明已经赋值为某对象,则移除引用if( *_refCount > 0 ){remove();}_obj = sptr._obj;_refCount = sptr._refCount;++(*_refCount);return *this;}protected:void remove(){--(*_refCount);//不仅需要删除原始对象,引用计数也需要删除,删除后要赋值NULLif( 0 == (*_refCount) ){delete _obj;free(_refCount);_obj = NULL;_refCount = NULL;}}public:T* _obj;unsigned* _refCount;//这里引用计数必须用指针,而且指向无符号整数,不用int的原因是【?】};void process(){int* ptr = new int;*ptr = 1;SmartPointer<int> sptr(ptr);cout<< "构造时sptr引用计数:" << *sptr._refCount << endl;// 1SmartPointer<int> copySptr(sptr);cout<< "拷贝构造sptr引用计数:" << *sptr._refCount << "  ,copySptr计数:" << *copySptr._refCount << endl;// 2 2SmartPointer<int>& equalSptr = sptr;cout<< "赋值后sptr引用计数:" << *sptr._refCount << "  ,equalSptr计数:" << *equalSptr._refCount << endl;// 1 2 实际为 2 2}int main(int argc, char* argv[]){process();getchar();return 0;}

0 0