#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);
//不仅需要删除原始对象,引用计数也需要删除,删除后要赋值NULL
if( 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;// 1
SmartPointer<int> copySptr(sptr);
cout<< "拷贝构造sptr引用计数:" << *sptr._refCount << " ,copySptr计数:" << *copySptr._refCount << endl;// 2 2
SmartPointer<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;
}
程序员面试金典: 9.13 C和C++ 13.8编写一个智能指针类
最新推荐文章于 2022-02-23 19:27:10 发布