带引用计数的智能指针shared_ptr、weak_ptr

智能指针的引入

由于C++语言没有自动内存回收机制,每次new出来的内存都要手动delete。

  • 忘记delete
  • 二次释放
  • 异常导致程序过早退出,没有执行delete
    用智能指针便可以有效缓解这类问题

理解智能指针

1.从较浅的层面看,智能指针是利用了一种叫做RAII(资源获取即初始化)的技术对普通的指针进行封装。因此智能指针实质是一个对象,行为表现的却像一个指针。

2.每次创建类的新对象时,初始化指针并将引用计数置为1;当对象作为另一对象的副本而创建时,拷贝构造函数拷贝指针并增加与之相应的引用计数;对一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用计数(如果引用计数为减至0,则删除对象),并增加右操作数所指对象的引用计数;调用析构函数时,析构函数减少引用计数(如果引用计数减至0,则删除基础对象)。

3.智能指针是存储指向动态分配(堆)对象指针的类。除了能够在适当的时间自动删除指向的对象外,他们的工作机制很像C++的内置指针。智能指针在面对异常的时候格外有用,因为他们能够确保正确的销毁动态分配的对象。他们也可以用于跟踪被多用户共享的动态分配对象。

智能指针的简单实现

template<typename T>
class CSmartPtr
{
   
public:
	// 构造函数
	CSmartPtr(T *ptr = nullptr)
		:mptr(ptr){
   }
	~CSmartPtr()
	{
   
		delete mptr;
	}
	
	
	T& operator*() {
    return *mptr; }
	const T& operator*()const {
    return *mptr; }
	T* operator->() {
    return mptr; }

	
private:
	T *mptr;  
};

int main()
{
   
	CSmartPtr<int>  ptr(new int(10));
	return 0;
}

由于ptr是栈上的智能指针对象,无论是函数正常执行结束还是异常结束,栈上的对象都会自动调用它的析构函数,保证释放资源。

仔细分析上述代码可以发现,我们没有给智能指针实现,拷贝构造函数,如果执行下面的语句,就会调用默认的拷贝构造函数进行浅拷贝,这样就会导致同一个资源析构两次,这是严重的错误。

CSmartPtr<int>  ptr1(ptr);

需要解决的问题

  • 浅拷贝问题
  • 多个智能指针指向同一个对象时,如何保证资源不被重复释放

解决方法

记录资源的引用计数类

class RefCnt
{
   
public:
	// 给资源添加引用计数
	void add(void *ptr)
	{
   
		auto it = mrefCntMap.find(ptr);
		if (it != mrefCntMap.end())
		{
   
			it->second++;
		}
		else
		{
   
			// make_pair(ptr,1);
			mrefCntMap.insert({
    ptr, 1 });
		}
	}
	// 给资源减少引用计数
	void del(void *ptr)
	{
   
		auto it = mrefCntMap.find(ptr);
		if (it != mrefCntMap.end())
		{
   
			if (--(it->second) == 0)
			{
   
				mrefCntMap.erase(it);
			}
		}
	}
	// 返回指定资源的引用计数
	int get(void *ptr)
	{
   
		auto it = mrefCntMap.find(ptr);
		if (it != mrefCntMap.end())
		{
   
			return it->second;
		}
		return 0;
	}
private:
	// 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值