首页 > 代码库 > 初探boost之smart_ptr库学习笔记
初探boost之smart_ptr库学习笔记
概述
Boost.smart_ptr库提供了六种智能指针,除了shared_ptr 和 weak_ptr 以外还包括 scoped_ptr 、scoped_array 、
shared_array 、intrusive_ptr 。他们的速度与原始指针相差无几,都是异常安全的,而且对于类型T也仅有一个要
求:类型T的析构函数不能抛出异常。
使用时包含头文件:
#include<boost/smart_ptr.hpp>
scoped_ptr
用法:
scoped_ptr 的构造函数接受一个类型为T* 的指针p,创建出一个scoped_ptr 类型对象,并在内部保存指针p。p必
须是一个new表达式动态分配的结果,或是个空指针(nullptr)。当scoped_ptr对象的生命期结束时,析构函数会
使用delete操作符自动销毁所保存的指针对象,从而正确的回收资源。
scoped_ptr同时把拷贝构造函数和赋值操作符都声明为私有的,禁止对智能指针的复制操作,也保证了它管理的指针
不能被转让所有权。
scoped_ptr重载了* 和 ->操作符,可以当普通指针使用。除此之外没有重载别的运算符,因此不能对其使用++、 --
== 、 != 等运算符。
举例
#include<boost/smart_ptr.hpp>#include<iostream>using namespace std;using namespace boost;int main(){ scoped_ptr<string> sp(new string("hello world")); cout<<*sp<<endl; cout<<sp->size()<<endl; return 0;}
scoped_array
用法:
构造函数接受的指针必须是 new [ ]的结果。
没有* 、 -> 操作符重载,提供 [ ]运算符,可以与普通数组一样用下标访问元素
举例:
#include<boost/smart_ptr.hpp>#include<iostream>using namespace std;using namespace boost;int main(){ scoped_array<int> sp(new int[10]{0,1,2,3,4,5,6,7,8,9}); for(int i=0;i<10;i++) cout<<sp[i]; return 0;}
shared_ptr
用法
shared_ptr实现的是引用型的智能指针,可以被自由的拷贝和赋值。当引用计数为0时,它才会删除被包装的动态分
配的对象。shared_ptr也可以安全的放到标准容器中,是在STL容器中存储指针的最标准解法。
构造函数
<1>shared_ptr() 无参,创建一个持有空指针的shared_ptr
<2>shared_ptr(T *p) 获得指向T类型指针p的管理权,引用计数+1
<3>shared_ptr(shared_ptr const & r) 从另一个shared_ptr获得指针的管理权,引用计数+1
<4>shared_ptr(std::auto_ptr<Y> const & r) 从一个auto_ptr获得指针的管理权,引用计数+1,auto_ptr失去管理
<5>operator= 赋值操作符可以用另一个shared_ptr或auto_ptr获得指针的管理权,其行为同构造函数。
reset函数
将引用计数减一,停止对指针的管理,除非引用计数为0,否则不会发生删除操作。
带参数的reset函数,原指针引用计数减一同时改为管理另一个指针。
检查引用计数函数
unique( ) //唯一时返回true
use_count( ) //返回引用计数个数
注:use_count应该仅仅用于测试,它不提供高效率的操作。而unique()则是可靠的,而且比use_count()快。
其他运算符操作
shared_ptr还支持比较运算,比较基于内部保存的指针 a.get() == b.get()。
shared_ptr还可以使用<<输出内部指针的值。
shared_ptr还可以使用operator<比较大小,同样基于内部保存的指针,因此可以被用于标准关联容器。
类型转换
shared_ptr提供了static_pointer_cast<T>() 、const_pointer_cast<T>() 、dynamic_pointer_cast<T>()。
它们与标准类型转换操作类似,但是返回的类型是shared_ptr。
举例:
#include<boost/smart_ptr.hpp>#include<iostream>using namespace std;using namespace boost;int main(){ int *ip = new int(10); boost::shared_ptr<int> sp(ip); cout<<sp.use_count(); boost::shared_ptr<int> sp2(sp); cout<<sp.use_count(); cout<<sp2.use_count(); sp2.reset(); cout<<sp.use_count(); cout<<sp.unique(); cout<<sp2.use_count(); return 0;}
输出:
122110
工厂函数
不仅消除了delete关键字,也消除了new关键字,显得对称。
举例:
#include<boost/smart_ptr.hpp>#include<iostream>using namespace std;using namespace boost;int main(){ boost::shared_ptr<int> sp = make_shared<int>(10); cout<<sp.use_count()<<endl; cout<<*sp<<endl; return 0;}
输出:
1
10
应用于标准容器
一种方法将容器作为shared_ptr管理的对象,如shared_ptr<list<T> >。
另一种方法将shared_ptr作为容器的元素,如vector<shared_ptr<T> >,因为shared_ptr支持拷贝和比较操作。
举例:
#include <boost/make_shared.hpp>#include<boost/smart_ptr.hpp>#include<iostream>#include<vector>using namespace std;using namespace boost;int main(){ typedef vector<boost::shared_ptr<int> > vs; vs v(10); int i = 0; for (vs::iterator pos = v.begin(); pos != v.end(); ++pos) { (*pos) = make_shared<int>(++i); cout << *(*pos) << ", "; } cout << endl; boost::shared_ptr<int> p = v[9]; *p = 100; cout << *v[9] << endl; return 0;}
shared_array
用法:
构造函数接受的指针必须是 new [ ]的结果。
没有* 、 -> 操作符重载,提供 [ ]运算符,可以与普通数组一样用下标访问元素
就像shared_ptr 和 scoped_array的结合
举例:
#include<boost/smart_ptr.hpp>#include<iostream>using namespace std;using namespace boost;int main(){ int *p = new int[100]; shared_array<int> sa(p); sa[0] = 1; cout<<sa[0]; return 0;}
weak_ptr
用法:
weak_ptr是为配合shared_ptr而引入的一种智能指针,它更像是shared_ptr的一个助手而不是智能指针,因为它不
具有普通指针的行为,没有重载*和->。它的最大作用在于协助shared_ptr工作,像旁观者观测资源的使用情况。
可以从一个shared_ptr或一个weak_ptr对象构造,获得资源的观测权。但weak_ptr没有共享资源,因此不用增加引
用计数的值,同样,在析构时也不会导致引用计数减少。
函数
use_count() 可以观测资源的引用计数。
expired()的功能等价于use_count==0,表示被观测的资源已经不存在。
lock()函数看从被观测的shared_ptr获得一个可用的shared_ptr对象,从而操作资源。但当expired()==true时,将
返回一个存储空指针的shared_ptr
举例:
#include<boost/smart_ptr.hpp>#include<iostream>using namespace std;using namespace boost;int main(){ boost::shared_ptr<int> sp(new int(10)); boost::weak_ptr<int> wp(sp); cout<<sp.unique()<<endl; if(!wp.expired()) { boost::shared_ptr<int> sp2 = wp.lock(); *sp2 = 100; cout<<sp2.use_count()<<endl; } cout<<sp.use_count()<<endl; cout<<*sp<<endl; return 0;}
intrusive_ptr
用法
intrusive_ptr是一个侵入式的引用计数型指针,可用于下面两种情形:
<1>对内存要求非常严格,必须与原始指针一样
<2>现存代码已经有了引用计数机制管理的对象