程序员面试金典: 9.13 C和C++ 13.8编写一个智能指针类

#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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值