智能指针——auto_ptr、shared_ptr、weak_ptr、scoped_ptr

总结:

1、auto_ptr 能够拷贝,能够转移所有权

2、scoped_ptr  不能赋值或拷贝,不能转移所有权

3、weak_ptr 仅能从weak_ptr、shared_ptr类型对象构造而来,不会增加引用计数

3、养成良好的习惯

(1)注意构造函数的区别

无论是使用auto_ptr还是shared_ptr,都永远不要写这样的代码:
A* pa = new A;
xxx_ptr ptr_a_1(pa);
xxx_ptr
ptr_a_2(pa);

这样,程序结束会调用两次析构函数。应该写成

xxx_ptr ptr_a_1(new A);
xxx_ptr
ptr_a_2(pa);

因为shared_ptr(const shared_ptr& r); 源对象是shared_ptr时,引用计数才会加1.

而template explicit shared_ptr(Y* p);
这个构造函数获得给定指针p的所有权。参数 p 必须是指向 Y 的有效指针。构造后引用计数设为1,所以第一种写法ptr_a_1、ptr_a_2引用计数都设为了1

(2)谨防shared_ptr相互引用造成的内存泄漏



#include

#include

#include


using namespace boost;

using namespacestd;

class Test{

public:

    Test(constchar* str){

        cout <<"Test():" << str << endl;

    }

    ~Test(){cout <<"~Test()" << endl;}

};

int main(){

    //scoped_ptr不能拷贝,所有权不能转移,自动回收资源

    /*exmple1*/

    scoped_ptr<string> sp(newstring("Hello, world!"));

    cout << *sp <<endl;

    cout << sp->size() <<endl;

    

    /*exmaple2*/

    scoped_ptr<int> p(newint);//equal int *p;

    if(p){

        *p = 100;

        cout << *p <<endl;

        int* p2 = p.get();

        cout << *p2 <<endl;

    }

        

    p.reset();//销毁内部对象并接受新的对象的所有权

    assert(p == 0);

    if(!p)

    {cout <<"scoped_ptr == null" << endl;}

    scoped_ptr<Test> fp(newTest("this is test class"));

    

    auto_ptr<int> ap(new int(10));

    scoped_ptr<int> sp1(ap);

    assert(ap.get() == 0);//ap不再拥有指针

    //int* p3 = ap.release(); //放弃内部对象的所有权,p3指向的值为10

    

    ap.reset(newint(20));//销毁内部对象并接受新的对象的所有权

    cout << *ap << "," << *sp1 << endl;

    

    auto_ptr<int> ap2;

    ap2 = ap;//转移所有权

    assert(ap.get() == 0);//ap不再拥有指针

    //scoped_ptr sp2(sp);  //编译不过

    //scoped_ptr sp2=sp;   //编译不过

}


运行结果:

Hello, world!

13

100

100

scoped_ptr == null

Test():this is test class

20,10

~Test()



#include

#include

#include

using namespace std;

using namespace boost;

class Test

{

    public:

    Test(){cout<<"Test()"<


    ~Test(){cout<<"~Test()"<

};

int main()

{

    shared_ptr p(new Test());

    //shared_ptr p1(p);

    //cout<

    //return 0;

    weak_ptr w(p); //不会增加引用计数,值为1

    while(!w.expired()){ //w.expired()为true说明已过期

        cout << w.use_count() << endl;

        shared_ptr t = w.lock();

        cout << w.use_count() << endl;

        if(w.use_count()==2){

            break;

        }

    }

    w.reset();

    cout << w.expired() << endl;

    return 0;

}


运行结果

Test()

1

2

1

~Test()


循环引用:

#include

#include

#include

#include


class parent;

class children;


typedef boost::shared_ptr parent_ptr;

typedef boost::shared_ptr children_ptr;


class parent

{

public:

    parent(){ std::cout<<"create parent\n";}

    ~parent() { std::cout <<"destroying parent\n"; }


public:

    children_ptr children;

};


class children

{

public:

    children() {std::cout<<"create children\n";}

    ~children() { std::cout <<"destroying children\n"; }


public:

    parent_ptr parent;

};



void test()

{

    parent_ptr father(new parent());

    children_ptr son(new children);


    father->children = son;

    son->parent = father;

}


int main()

{

    std::cout<<"begin test...\n";

    test();

    std::cout<<"end test...\n";

    return 0;

}


运行结果:

begin test...

create parent

create children

end test...


由于parent和children对象互相引用,它们的引用计数都是1,不能自动释放,并且此时这两个对象再无法访问到。这就引起了c++中那臭名昭著的内存泄漏。


修改为weak_ptr:

#include

#include

#include

#include


class parent;

class children;


typedef boost::shared_ptr parent_ptr;

typedef boost::shared_ptr children_ptr;

typedef boost::weak_ptr parent_wptr;

class parent

{

public:

    parent(){ std::cout<<"create parent\n";}

    ~parent() { std::cout <<"destroying parent\n"; }


public:

    children_ptr children;

};



class children

{

public:

    children() {std::cout<<"create children\n";}

    ~children() { std::cout <<"destroying children\n"; }


public:


    parent_wptr parent;

};



void test()

{

    parent_ptr father(new parent());

    children_ptr son(new children());


    father->children = son;

    son->parent = father;

}


int main()

{

    std::cout<<"begin test...\n";

    test();

    std::cout<<"end test...\n";

    return 0;

}


运行结果:

begin test...

create parent

create children

destroying parent

destroying children

end test...

你可能感兴趣的:(C++)