首页 > 代码库 > boost库学习之 shared_ptr

boost库学习之 shared_ptr

shared_ptr与scoped_ptr都包装在堆上分配的动态对象,都重载了*和->操作符以模仿原始指针行为,但shared_ptr实现的是引用计数型的智能指针,当没有代码使用时计数为0,此时释放被包装的动态分配的内存。
shared_ptr可以被自由地拷贝和赋值。shared_ptr可以安全地放到标准容器中。
引用《boost程序库完全开发指南》中的话:“shared_ptr非常有价值、非常重要、非常有用。”
shared_ptr有多种形式的构造函数,应用于各种可能的情形:
1.无参的shared_ptr()创建一个持有空指针的shared_ptr
2.shared_ptr(Y *p)获得指向类型T的指针p的管理权,同时引用计数置为1.
3.shared_ptr(shared_ptr const &r)从另一个shared_ptr获得指针的管理权, 引用计数加1
4.shared_ptr(std::auto_ptr<Y> &r)从一个auto_ptr获得指针的管理权,引用计数置为1
5.重载了=操作符,可以从另一个shared_ptr或auto_ptr获得指针的管理权。行为同构造函数。
6.shared_ptr(Y *p, D d)行为类似shared_ptr(Y *p),参数d指定了析构时的定制删除器。
reset()函数与scoped_ptr的reset()函数不同,它将引用计数减1
unique()在shared_ptr指针唯一所有者时返回true
use_count()返回当前指针的引用计数。多应用于测试或调试,不提供高效率的操作,unique()速度更快。
支持比较,可以测试两个shared_ptr的相等或不等。
if (a.get() == b.get())
{
}

shared_ptr<int> p(new int(1));  //引用计数置为1
shared_ptr<int> p2(p);          //引用计数+1, 为2
cout << p.use_count() << endl;


shared_ptr很好的消除了显式的delete调用,但构造还需要new.为了消除不对称性,也可以调用头文件<boost/make_shared.hpp>中的make_shared<T>()函数来消除new.
make_shared() 函数最多接受10个参数,然后传递给shared_ptr所包裹指针的类型的构造函数。
应用于标准容器
有两种方式可以将shared_ptr应用于标准容器,
1.将容器作为shared_ptr管理的对象,如shared_ptr<list<T>>,用法与普通shared_ptr没有区别
2.另一种用法是将shared_ptr作为容器的元素。如list<shared_ptr<T>>.因为shared_ptr支持拷贝语义和比较操作,符合标准容器对元素的需求。标准容器不能容纳auto_ptr和scoped_ptr.
定制删除器
shared_ptr有一种shared_ptr(Y *p, D d)形式的构造函数,第一个参数是要被管理的指针,第二个参数d可以是函数对象,也可以是函数指针。告诉shared_ptr在析构时不使用delete来操作指针,而是调用d(p).
即把delete(p)换成d(p),d(p)不能抛出异常。
get_deleter(shared_ptr<T>const& p)函数可以返回删除器的指针
例如
shared_ptr<FILE> fp(fopen("a.txt", "r"), fclose);
当离开作用域时,shared_ptr自动调用fclose关闭文件
shared_ptr高级用法
void*指针可以指向任意类型,shared_ptr<void>就是一个泛型指针容器,可以管理任意类型的指针。但同时也丧失了原来的类型信息,
在使用时可以用static_pointer_cast<T>转型为原来的指针。
基于shared_ptr<void>和删除器,shared_ptr<void>可以实现退出作用域时调用任意函数的效果。
{
    shared_ptr<void> p((void*)0, func);
}


退出作用域时调用函数func()
shared_array
shared_array用于管理动态数组,接口与功能几乎与shared_ptr相同。
主要区别:
管理的指针p必须是new[]的结果而不是new表达式的结果
没有*, ->操作符重载,因为持有的不是一个普通指针
重载了[],可以像普通数组一样用下标访问元素
{
    int *array = new int[100];
    shared_ptr<int> sa(array);
    shared_ptr<int> sa2 = sa; //共享数组,引用计数增加
    sa[0] = 0;                //重载了[]
}


boost库学习之 shared_ptr