C/C++之智能指针shared_ptr

1、定义

shared_ptr的作用有如同指针,但会记录有多少个shared_ptrs共同指向一个对象。这便是所谓的引用计数(reference counting)。一旦最后一个这样的指针被销毁,也就是一旦某个对象的引用计数变为0,这个对象会被自动删除。这在非环形数据结构中防止资源泄露很有帮助。

auto_ptr由于它的破坏性复制语义,无法满足标准容器对元素的要求,因而不能放在标准容器中;如果我们希望当容器析构时能自动把它容纳的指针元素所指的对象删除时,通常采用一些间接的方式来实现,显得比较繁琐。boost库中提供了一种新型的智能指针shared_ptr,它解决了在多个指针间共享对象所有权的问题,同时也满足容器对元素的要求,因而可以安全地放入容器中。

2、shared_ptr用法

示例一:

#include "boost/shared_ptr.hpp"                                                                                                                                                 
#include <vector>
#include <iostream>

class A 
{
public:
    virtual void sing()=0;

protected:
    virtual ~A() 
    {
        std::cout << "~deconstruct A" << std::endl;
    }

};

class B : public A 
{
public:
    void sing() 
    {
        std::cout << "Do re mi fa so la" << std::endl;
    }

    ~B()
    {
        std::cout << "~deconstruct B" << std::endl;
    }
};

boost::shared_ptr<A> createA() 
{
    boost::shared_ptr<A> p(new B());
    return p;
}


int main() 
{
    typedef std::vector<boost::shared_ptr<A> > container_type;
    typedef container_type::iterator iterator;
    container_type container;
    for (int i=0; i<5; ++i) 
    {
        container.push_back(createA());
    }

    std::cout << "The choir is gathered: \n";
    iterator end=container.end();
    for (iterator it=container.begin();it!=end;++it) 
    {
        (*it)->sing();
    }
}

这里有两个类, A和 B, 各有一个虚拟成员函数 sing. B从 A公有继承而来,并且如你所见,工厂函数 createA返回一个动态分配的B的实例,包装在shared_ptr<A>里。在 main里, 一个包含shared_ptr<A>的 std::vector被放入5个元素,最后对每个元素调用sing。如果我们用裸指针作为元素,那些对象需要被手工删除。而在这个例子里,删除是自动的,因为在vector的生存期中,每个shared_ptr的引用计数都保持为1;当 vector被销毁,所有引用计数器都将变为零,所有对象都被删除。有趣的是,即使 A的析构函数没有声明为 virtual, shared_ptr也会正确调用 B的析构函数。

输出结果:

The choir is gathered: 
Do re mi fa so la
Do re mi fa so la
Do re mi fa so la
Do re mi fa so la
Do re mi fa so la
~deconstruct B
~deconstruct A
~deconstruct B
~deconstruct A
~deconstruct B
~deconstruct A
~deconstruct B
~deconstruct A
~deconstruct B
~deconstruct A

示例二:

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.reset();                                     //停止shared_ptr的使用  
assert(!sp);                                    //sp不再持有任何指针(空指针)

示例三:

#include "boost/shared_ptr.hpp"
#include <vector>
#include <iostream>

using namespace std;
using namespace boost;

class shared //一个拥有shared_ptr的类  
{
private:
    shared_ptr<int> p;                          //shared_ptr成员变量  

public:
    shared(shared_ptr<int> p_):p(p_){}          //构造函数初始化shared_ptr      
    void print()                                //输出shared_ptr的引用计数和指向的值      
    {
        cout << "count:" << p.use_count() << " v =" <<*p << endl;                                                                                                               
    }
};

void print_func(shared_ptr<int> p)                //使用shared_ptr作为函数参数  
{
        //同样输出shared_ptr的引用计数和指向的值      
        cout << "count:" << p.use_count() << " v=" <<*p << endl;
}

int main()
{
    shared_ptr<int> p(new int(100));
    shared s1(p), s2(p);                        //构造两个自定义类       

    s1.print();
    s2.print();

    *p = 20;                                    //修改shared_ptr所指的值      
    print_func(p);
    s1.print();
}

输出结果:

count:3 v =100
count:3 v =100
count:4 v=20
count:3 v =20

 

 

C/C++之智能指针shared_ptr,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。