shared_ptr循环引用&定置删除器

shared_ptr虽然方便,但是它有着一个致命的缺陷就是循环引用问题,因为shared_ptr本身并没有能力解决这个问题,所以我们又引入了弱指针weak_ptr来辅助shared_ptr解决这个问题。

十多年的陕州网站建设经验,针对设计、前端、开发、售后、文案、推广等六对一服务,响应快,48小时及时工作处理。营销型网站的优势是能够根据用户设备显示端的尺寸不同,自动调整陕州建站的显示方式,使网站能够适用不同显示终端,在浏览器中调整网站的宽度,无论在任何一种浏览器上浏览网站,都能展现优雅布局与设计,从而大程度地提升浏览体验。创新互联从事“陕州网站设计”,“陕州网站推广”以来,每个客户项目都认真落实执行。

那么循环引用又是什么场景?

举个栗子:

假设现在我们要创建一个双向×××链表,但是这个链表的指针域全部都用shared_ptr维护:

struct Node

{

    int _data;

    shared_ptr _next;

    shared_ptr _prev;

}

假设现在先创建两个结点,并用shared_ptr维护这两个结点:

shared_ptr sp1(new Node);

shared_ptr sp2(new Node);

现在将这两个指针互相连接:

sp1->_next=sp2;

sp2->prev=sp1;

shared_ptr循环引用&定置删除器

shared_ptr循环引用&定置删除器

   为了解决循化引用问题,我们又引入了weak_ptr弱指针,用来辅助shared_ptr。注意weak_ptr不能单独使用,必须辅助shared_ptr才能使用。weak_ptr是一种不控制所指向对象生存周期的智能指针,它指向一个由shared_ptr管理的对象,将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。一但最后一个指向对象的shared_ptr被销毁,对象就会被销毁,即使有weak_ptr指向对象,对象还是会被释放。

例:

所以为了解决上面栗子中的循环引用问题,我们可以将指针域的智能指针声明为弱指针。

struct Node

{

    int _data;

    weak_ptr _next;

    weak_ptr _prev;

}

二、定置删除器

   一般情况下,我们都用智能指针是用来管理动态内存的,其实智能指针是用来管理资源的,资源很多,动态内存只是资源的一种,比如说我们可以用智能指针来管理文件,那么我们就不能用智能指针默认的删除器了,因为要管理文件的话最后是fclose,而不是delete,所以我们就必须自己定制一个删除器。

例:以管理文件为例,实现定置删除器。

要实现定置删除器,就要用到仿函数:仿函数就是将"()"重载。

//定置删除器的仿函数
struct Fclose
{
       void operator()(void *ptr)
       {
              fclose((FILE *)ptr);
              cout << "fclose()" << endl;
       }
};
void test()
{
       boost::shared_ptr sp(fopen("test.txt","w"),Fclose());    //调用构造函数构造一个匿名对象传递过去,文件正常关闭
}

再举一个栗子:
用智能指针管理malloc开辟的动态内存,那么我们在释放的时候就要用free释放:
//定置删除器的仿函数
struct Free
{
       void operator()(void *ptr)
       {
              free(ptr);
       }
};
void test()
{
       boost::shared_ptr sp((int *)malloc(sizeof(int)),Free());        //能够正确的释放空间
}


三、简单的实现一个有定置删除器的shared_ptr

struct Fclose
{
	void operator()(void *ptr)
	{
		fclose((FILE *)ptr);
		cout << "fclose()" << endl;
	}
};

struct Free
{
	void operator()(void *ptr)
	{
		free(ptr);
		cout << "free()" <
class SharedPtr            //采用引用计数,实现一个可以有多个指针指向同一块内存的类模板,SharedPtr是类模板,不是智能指针类型
{
public:
	SharedPtr(T* ptr, D del = DefaultDel());
	SharedPtr(const SharedPtr& sp);
	SharedPtr& operator=(SharedPtr sp);
	T& operator*();
	T* operator->();
	~SharedPtr();
	int Count()
	{
		return *_pCount;
	}
private:
	void Release()
	{
		if (--(*_pCount) == 0)
		{
			_del(_ptr);
 			delete _pCount;
			_ptr = NULL;
			_pCount = NULL;
		}
	}
private:
	T* _ptr;
	int* _pCount;
	D _del;
};


template
SharedPtr::SharedPtr(T* ptr,D del)
:_ptr(ptr)
, _pCount(new int(1))
,_del(del){}

template
SharedPtr::SharedPtr(const SharedPtr& sp)
{
	_ptr = sp._ptr;
	_pCount= sp._pCount;
	++(*_pCount);
}

template
SharedPtr& SharedPtr::operator=(SharedPtr sp)
{
	std::swap(sp._ptr,_ptr);
	std::swap(sp._pCount,_pCount);
	return *this;
}

template
T& SharedPtr::operator*()
{
	return *_ptr;
}

template
T* SharedPtr::operator->()
{
	return _ptr;
}

template
SharedPtr::~SharedPtr()
{
	Release();
}



//测试用例
void test()
{
	SharedPtr sp(new int(1));
	SharedPtr sp1(fopen("test.txt","w"),Fclose());
	SharedPtr sp3((string *)malloc(sizeof(string)),Free());
}


int main()
{
	test();
	system("pause");
	return 0;
}

新闻名称:shared_ptr循环引用&定置删除器
地址分享:http://myzitong.com/article/ighedg.html