boost::shared_ptr
Posted kloseer
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了boost::shared_ptr相关的知识,希望对你有一定的参考价值。
shared_ptr
shared_ptr实现的是引用计数型的智能指针,可以被自由地拷贝和赋值,在任意的地方共享它,当没有代码使用它时才删除被包装的动态分配的对象。
类摘要:
template<class T>
class shared_ptr
{
public:
typedef T element_type; //内部类型定义
shared_ptr(); //构造函数
template<class Y> explicit shared_ptr(Y *p);
template<class Y,class D> shared_ptr(Y *p,D d);
~shared_ptr(); //析构函数
shared_ptr(shared_ptr const & r);
shared_ptr & operator=(shared_ptr const & r); //赋值操作
template<class Y> shared_ptr & opeerator=(shared_ptr<Y> const & r);
void reset(); //重置智能指针
template<class Y> void reset(Y* p);
template<class Y,class D> void reset(Y* p,D d);
T& operator*() const; //操作符重载
T* operator->() const; //操作符重载
T* get() const; //获得原始指针
bool unique() const; //是否唯一
long use_count const; //引用计数,应该仅仅用于测试或者调试,不提供高效的操作
explicit operator bool() const;//显式bool值转型
void swap(shared_ptr & b); //交换指针
};
操作函数:
shared_ptr有多种形式的构造函数,应用于各种可能的情形:
无参的shared_ptr()创建一个持有空指针的shared_ptr。
shared_ptr(Y *p)获得指向类型T的指针p的管理权,同事引用计数置为1,这个构造函数要求Y类型必须能够转换为T类型。
shared_ptr(shared_ptr const & r)从另外一个shared_ptr获得指针的管理权,同时引用计数加1,结果是两个shared_ptr共享一个指针的管理权。
operator=赋值操作符可以从另外一个shared_ptr获得指针的管理权,其行为同构造函数。
shared_ptr(Y* p,D d)行为类似shared_ptr(Y* p),但使用参数d指定了析构函数的定制删除器,而不是简单地使用delete。
别名构造函数,不增加引用计数的特殊用法。
shared_ptr的reset()函数的行为与scoped_ptr也不尽相同,它的作用是将引用计数减一,停止对指针的共享,除非引用计数为0,否则不会发生删除操作,带参数的reset()则类型相同形式的构造函数,原指针引用计数减1的同时改为管理另一个指针。
shared_ptr支持比较运算,可以测试两个shared_ptr的相等或不相等,比较基于内部的保存的指针,相当于a.get() == b.get().shared_ptr可以使用operator<比较大小(不提供之外的比较运算符)
用法:shared_ptr提供基本的线程安全保证,一个shared_ptr可以被多个线程安全读取,但其他的访问形式结果是未定义的。基本用法例子:
shared_ptr<int> sp(new int(10)); //一个指向整数的shared_ptr
assert(sp.unique()); //现在shared_ptr是指针的唯一的持有者
shared_ptr<int> sp2 = sp; //第二个shared_ptr,拷贝构造函数
assert(sp == sp2 && sp.use_count() == 2); //两个shared_ptr相等,指向同一个对象,引用计数为2
*sp2 = 100; //使用解引用操作符修改被指对象,
assert*sp == 100另外一个shared_ptr也同时被修改
sp.resert(); //停止shared_ptr的使用
assert(!sp); //sp不再持有任何指针
第二个例子示范了较复杂的用法:
class shared
{
private:
shared_ptr<int> p;
public:
shared(shared_ptr<int> p_):p(p_) {}
void print()
{
cout<<"count:"<<p.use_count()<<" v="<<*p<<endl;
}
};
voif print_func(shared_ptr<int> p)
{
cout<<"count:"<<p.use_count()
<<"v="<<*p<<endl;
}
int man()
{
shared_ptr<int> p(new int(100));
shared s1(p),s2(p);
s1.print();
s2.print();
*p = 20;
print_func(p);
s1.print();
}
//运行结果:
count:3 v=100
count:3 v=100
count:4 v=20
count:3 v=20
在声明了shared_ptr和两个shared类实例后,指针被它们所共享,因此引用计数为3,print_func()内部拷贝了一个shared_ptr对象,因此引用计数在增加1,但当退出函数时拷贝自动析构,引用计数又恢复到3.
工厂函数:
虽然shared_ptr很好的包装了new的表达式,但过多的显示new操作符也是问题,显式delete调用应该使用工厂函数来解决。smart_ptr库提供了一个工厂函数make_shared(),来消除显式的new调用,声明如下:
template<class T,class... Args>
typename boost::detail::sp_if_not_array<T>::tyoe
make_shared(Args && ...args);
make_shared()函数可以接受若干个参数,然后把它们传递给类型为T的构造函数,创建一个shared_ptr
int main(){
auto = make_shared<string>("make_shared");
auto = make_shared<vector<int> >(10,2);
assert(spv->size() == 10);
}
定制删除器:
shared_ptr(Y * p,D d)的第一个参数是要被管理的指针,第二个删除器参数d则表示在析构时不是使用delete来删除指针p,而是用d来操作。d也可以是一个函数对象或者一个函数指针,对删除器的要求是它必须是可拷贝的,行为必须像delete,不能抛出异常。
假设我们有一组操作socket的函数,使用一个socket_t类:
class socket_t { ... };
socket_t* open_socket()
{
cout<<"open_socket"<<endl;
return new socket_t;
}
void close_socket(socket_t * s)
{
cout<<"close_socket"<<endl;
...
}
资源释放操作就是函数close_socket(),可以用shared_ptr管理socket资源:
socket_t *s = open_socket();
shared_ptr<socket_t> p(s,&close_socket);
当离开作用域时,shared_ptr会自动调用close_socket()函数关闭socket。
以上是关于boost::shared_ptr的主要内容,如果未能解决你的问题,请参考以下文章
使用带有 boost::shared_ptr 的基类在地图中查找