2014-11-23 27 views
9

我讀過weak_pointers可以用來破壞循環引用。如何使用weak_ptr破壞shared_ptr循環引用

考慮一個循環引用

struct A 
{ 
boost::shared_ptr<A> shrd_ptr; 
}; 


boost::shared_ptr<A> ptr_A(boost::make_shared<A>()); 
boost::shared_ptr<A> ptr_b(boost::make_shared<A>()); 
ptr_A->shrd_ptr = ptr_b; 
ptr_b->shrd_ptr = ptr_A; 

現在上面的循環引用的情況下的下面的例子,我想知道我可以用weak_ptr突破 上面的循環引用?

更新: 根據收到的建議,我想出了以下內容:

struct A 
{ 
    boost::weak_ptr<A> wk_ptr; 
}; 

    boost::shared_ptr<A> ptr_A (boost::make_shared<A>()); 
    boost::shared_ptr<A> ptr_B (boost::make_shared<A>()); 
    ptr_A->wk_ptr = ptr_B; 
    ptr_B->wk_ptr = ptr_A; 

這會不會是正確的做法?

+1

將'A :: shrd_ptr'改爲'boost :: weak_ptr'並在其他地方保存'shared_ptr'。 – 2014-11-23 05:17:09

回答

23

循環引用的典型的例子是,你有兩個類AB其中AB參考其具有A參考:

#include <memory> 
#include <iostream> 

struct B; 
struct A { 
    std::shared_ptr<B> b; 
    ~A() { std::cout << "~A()\n"; } 
}; 

struct B { 
    std::shared_ptr<A> a; 
    ~B() { std::cout << "~B()\n"; } 
}; 

void useAnB() { 
    auto a = std::make_shared<A>(); 
    auto b = std::make_shared<B>(); 
    a->b = b; 
    b->a = a; 
} 

int main() { 
    useAnB(); 
    std::cout << "Finished using A and B\n"; 
} 

如果兩個引用shared_ptr那麼說ABB的所有權歸屬爲A,應該響鈴。換句話說,A保持B活着,B保持A活着。

在這個例子中的實例abuseAnB()功能僅用於所以我們想,當函數結束,但我們可以看到,當我們運行程序的析構函數不叫他們被摧毀。

解決方案是決定誰擁有誰。比方說A擁有BB不擁有A那麼我們用weak_ptr像這樣替換B引用A

struct B { 
    std::weak_ptr<A> a; 
    ~B() { std::cout << "~B()\n"; } 
}; 

那麼,如果我們運行程序,我們看到ab如我們預期被破壞。

Live demo

編輯:在你的情況,你建議的方法看起來完全有效的。將所有權從A中除去,而其他東西則歸於A

+0

一個很好的答案 - 可惜我只能給它+1 – 2014-11-23 08:07:24

+0

如果我們稍後從a.lock()創建shared_ptr,問題(循環引用)會保留嗎? – 2016-05-09 09:36:03

+1

@Explorer_N提供'B'不會永久保留從'a.lock()'創建的'shared_ptr',那麼它就可以。 [這是現場演示的擴展版本](http://melpon.org/wandbox/permlink/mdIkQ3QbFhaskdro),其中包括使用'a.lock()'的示例。 – 2016-05-09 09:45:12