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 的对象并返回,通常make_shared()函数比直接创建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笔记

使用带有 boost::shared_ptr 的基类在地图中查找

boost::shared_ptr

boost shared_ptr 初始化为类成员

返回 boost::shared_ptr 和从返回的原始指针构造 boost::shared_ptr 有啥区别?

boost库之内存管理shared_ptr