c++中智能指针(二)

17 篇文章 1 订阅

一、shared_ptr的循环引用问题

在上篇文章中介绍了智能指针的基本知识,我们感觉shared_ptr好像特别厉害的样子,其

实它就是特别厉害,只是它有循环引用的问题,看下边的代码:

struct Node
{
	int _data;
	shared_ptr<Node> _next;
	shared_ptr<Node> _prev;
};
void test()
{
	shared_ptr<Node> sp1(new Node);
	shared_ptr<Node> sp2(new Node);
	cout << sp1.use_count() << endl;
	cout << sp2.use_count() << endl;
	sp1->_next = sp2;
	sp2->_prev = sp1;
	cout << sp1.use_count() << endl;
	cout << sp2.use_count() << endl;
}


上边的程序最终会输出1 1 2 2(数字之间以回车间隔),程序结束时,sp1和 sp2并不

会被析构(引用计数未被变为0)。下边图解。


注意:上边画绿线部分提到sp1和sp2都被释放,并不是空间真正被释放,而是相应空间

的引用计数减1.

那么,该如何解决这个问题呢?

我们引入了weak_ptr弱指针,它是用来辅助shared_ptr,并不可以单独使用。将一

weak_ptr绑定到一个shared_ptr,并不会改变shared_ptr的引用计数,一旦最后一个

指向对象的shared_ptr被销毁,对象就会被销毁,即使有weak_ptr指向对象,对象还是

会被释放。所以,上边定义的Node结构体改成下边这样,就能解决循环引用的问题。

struct Node
{
	int _data;
	weak_ptr<Node> _next;
	weak_ptr<Node> _prev;
};


二、定制删除器

智能指针的引入是为了解决因程序执行流的改变而引起的内存泄漏的问题。在构造函数

中开辟和初始化,在析构函数中完成清理工作。智能指针是模板,所以就应该可以解决

各种类型的内存泄漏问题。在构造函数中打开的文件,在析构函数中完成文件的关闭,

在构造函数中malloc开辟的空间,在析构函数中用free释放。所以,我们必须为每一种

类型写出对应的内存释放的函数。

通过仿函数(重载())来实现。下边展示定制删除器的模拟实现:

#include<iostream>
using namespace std;
#include<boost/shared_ptr.hpp>

template<typename T,typename D = DefaultDelete>
class SharedPtr
{
public:
	SharedPtr(T* ptr)
		:_ptr(ptr)
		,_pCount(new int (1))
		,_del(D())
	{}
	~SharedPtr()
	{
		if (--*_pCount == 0)
		{
			//delete _ptr;
			_del(_ptr);
			delete _pCount;
		}
	}
	SharedPtr(const SharedPtr<T,D>& sp)
	{
		_ptr = sp._ptr;
		_pCount = sp._pCount;
		++*_pCount;
	}
	SharedPtr<T,D>& operator=(const SharedPtr<T,D>& sp)
	{
		if (_ptr != sp._ptr)
		{
			if (_ptr != nullptr)
			{
				if (--*_pCount == 0)
				{
					//delete _ptr;
					_del(_ptr);
					delete _pCount;
				}
			}
			else
			{
				_ptr = sp._ptr;
				_pCount = sp._pCount;
				++(*_pCount);
			}
		}
		return *this;
	}
private:
	T* _ptr;
	int* _pCount;
	D _del;
};
//默认删除器
struct DefaultDelete
{
	void operator() (void* ptr)
	{
		delete ptr;
	}
};
struct Fclose
{
	void operator() (void* ptr)
	{
		fclose((FILE* )ptr);
	}
};
struct Free
{
	void operator() (void* ptr)
	{
		free(ptr);
	}
};
void test_del()
{
	SharedPtr<int>sp1(new int (1));
	SharedPtr<FILE,Fclose>sp2(fopen("hello.txt","w"));
}



当智能指针管理的是文件时,出作用域时就会调用关闭文件的函数。这就是所谓的定制

删除器。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值