shared_ptr智能指针的简单实现

shared_ptr是一种智能指针数据结构,除了具有智能指针的基本功能——自动管理资源释放外,还有一个特征就是"share",我理解所谓的“share”就是多个shared_ptr共同分享同一处资源,避免了资源的拷贝。比如,当执行拷贝构造函数操作时:

class X{...};

shared_ptr<X> px1(new X());
shared_ptr<X> px2(px1);

或是赋值操作时:

class X{...};

shared_ptr<X> px1(new X(...));
shared_ptr<X> px2(new X(...));
px2 = px1;

shared_ptr不进行资源的拷贝,而是将内部的指针指向相应的资源即可。以上例子中,px2并不会从px1中拷贝资源,而是将内部指针指向px1中的资源。

那么px2或px1被销毁时会发生什么?会将其指向的内部资源同时销毁吗?不会。现在的资源是大家公用的,不能被随意销毁。shared_ptr是采用引用计数(reference counting)来控制资源的指向和销毁。内部资源会伴有一个计数值count,count表示有多少个shared_ptr指向该资源,每当有一个新的shared_ptr指向该资源时,count值加1,当有一个指向该资源的shared_ptr销毁时,count值减1,当count变为0时,证明所有指向该资源的shared_ptr已经销毁,此时内部资源也被销毁。

 

自己写了一个简单的shared_ptr模板类,如下:

template<class T>
class my_shared_ptr{
public:
	my_shared_ptr(T* pt){
		_pBlock = new ControlBlock(pt);
	}
	my_shared_ptr(const my_shared_ptr& rhs){
		_pBlock = rhs._pBlock;
		_pBlock->ref_count++;
	}
	~my_shared_ptr(){
		_pBlock->ref_count --;
		if(0 == _pBlock->ref_count)
			delete _pBlock;
	}
	my_shared_ptr& operator=(const my_shared_ptr& rhs){
		if(this == &rhs)
			return *this;

		_pBlock->ref_count --;
		if(0 == _pBlock->ref_count)
			delete _pBlock;

		_pBlock = rhs._pBlock;
		_pBlock->ref_count++;
	}

	T* get(){return _pBlock->_ptr;}
	T* operator->(){return _pBlock->_ptr;}
	void reset(T* pt){
		_pBlock->ref_count --;
		if(0 == _pBlock->ref_count)
			delete _pBlock;

		_pBlock = new ControlBlock(pt);
	}

private:
	struct ControlBlock{
		int ref_count;
		T* _ptr;
		ControlBlock(T* pt){
			_ptr = pt;
			ref_count = 1;
		}
		~ControlBlock(){
			delete _ptr;
		}
	};
	ControlBlock* _pBlock;
};

my_shared_ptr内部有一个ControlBlock管理内部资源,同时有一个计数值ref_count标记指向该内部资源的my_shared_ptr个数。在拷贝构造函数和赋值操作符中,都有:

_pBlock = rhs._pBlock;
_pBlock->ref_count++;

语句,这两句表示当发生my_shared_ptr的拷贝时,不拷贝内部资源,而是将内部指针指向同样的内部资源,并增加计数值。

在析构函数中可以看到如下语句:

_pBlock->ref_count --;
if(0 == _pBlock->ref_count)
	delete _pBlock;

表示内部资源不是随意销毁的,析构函数会减小计数值,当计数值变为0时,内部资源才会销毁。
在赋值操作符函数中,首先进行自检,其次释放本身指向的内部资源,之后指向新的内部资源,并更新计数值。

 

测试程序如下:

#include "my_shared_ptr.h"
#include <iostream>
using namespace std;

class X{
public:
	X(int i):_val(i){
		cout << "X(" << _val << ") constructed." << endl;
	}
	~X(){
		cout << "X(" << _val << ") destructed." << endl;
	}
	void print(){
		cout << "X(" << _val << ")::print()." << endl;
	}
private:
	int _val;
};


int main(){

	my_shared_ptr<X> shared_px1(new X(10));
	my_shared_ptr<X> shared_px2(new X(20));

	shared_px1->print();
	shared_px2->print();

	shared_px2 = shared_px1;

	shared_px1->print();
	shared_px2->print();
}

执行结果如下:

X(10) constructed.
X(20) constructed.
X(10)::print().
X(20)::print().
X(20) destructed.
X(10)::print().
X(10)::print().
X(10) destructed.

可以看到,在执行赋值操作符函数后,shared_px2所指向的内部资源被销毁, 因为X(20)被析构;之后shard_px2和shared_px1指向了同一个内部资源,因为都打印了X(10)::print(). 程序结束时,所有内部资源都被自动销毁。


 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值