C++智能指針之強、弱智能指針使用以及用弱智能指針解決強智能指針的循環(交叉)引用解決方法

  • 強智能指針:資源每被強智能指針引用一次,引用計數+1,釋放引用計數-1,如shared_ptr;
  • 弱智能指針:僅僅起到觀察作用,觀察對象釋放還存在,也就是說對象的引用計數是否等於0,如weak_ptr.

強智能指針的使用,帶來資源的交叉引用問題:



class B;

class A{
public:
    A(){ std::cout<<"A()"<<std::endl; }
    ~A() { std::cout<<" ~A()"<<std::endl; }
    shared_ptr<B> ptrb;
};

class B{
public:
    B(){ std::cout<<"B()"<<std::endl; }
    ~B() { std::cout<<" ~B()"<<std::endl; }
    shared_ptr<A> ptra;
};

int main(){
    shared_ptr<A> pa(new A());
    shared_ptr<B> pb(new B());

    std::cout<<pa.use_count()<<std::endl;//打印對象pa的引用計數
    std::cout<<pb.use_count()<<std::endl;

    pa->ptrb = pb;
    pb->ptra = pa;

    std::cout<<pa.use_count()<<std::endl;
    std::cout<<pb.use_count()<<std::endl;

    return 0;
}

在這裏插入圖片描述
解決上述問題,引入弱智能指針:

class B;

class A{
public:
    A(){ std::cout<<"A()"<<std::endl; }
    ~A() { std::cout<<" ~A()"<<std::endl; }
    weak_ptr<B> ptrb;

    void show(){
        std::cout<<"A::show()"<<std::endl;
    }
};

class B{
public:
    B(){ std::cout<<"B()"<<std::endl; }
    ~B() { std::cout<<" ~B()"<<std::endl; }
    weak_ptr<A> ptra; //資源引用時用弱智能指針,而不是強智能指針

    void CallAshow(){
        //將ptra提升爲強智能指針,調用lock(),否則無法訪問A的方法,只能起觀察的作用
        shared_ptr<A> p = ptra.lock();
        if(p != nullptr){
            p->show();
        }
    }
};

int main(){
    shared_ptr<A> pa(new A());
    shared_ptr<B> pb(new B());

    pa->ptrb = pb;
    pb->ptra = pa;

    pb->CallAshow();
    std::cout<<pa.use_count()<<std::endl;
    std::cout<<pb.use_count()<<std::endl;
    return 0;
}

執行結果:

A()
B()
A::show()
1
1
~B()
~A()

總結:

  1. 強智能指針交叉引用會造成資源泄露問題,引入弱智能指針解決;
  2. 強智能指針引起引用計數+1,弱智能指針不會引起引用計數+1;
  3. 弱智能智能在有需要的時候可以提升爲強智能指針,通過判斷返回值是否爲nullptr查看是否提升成功;
weak_ptr<A> ptra;
shared_ptr<A> p = ptra.lock();
if(p != nullptr){
 	//do something        
 }
  1. shared_ptr和weak_ptr都是線程安全的智能智能指針;
  2. 定義的地方或者生成資源的地方一定的是強智能指針,引用資源的地方一定使用弱智能指針。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章