2016-06-28 5 views
4

次のコード例では、Bのオブジェクトが存在する限り、構造体B内に構造体Aのインスタンスが1つ存在する必要があります。例は期待通りに機能します。unique_ptrのrefcountの代わり

#include <memory> 
#include <iostream> 
#include <mutex> 

struct A 
{ 
    A() { std::cout << "A() called" << std::endl; } 
    ~A() { std::cout << "~A() called" << std::endl; } 
}; 

struct B 
{ 
    B() 
    { 
     std::cout << "B() called" << std::endl; 

     std::lock_guard<std::mutex> guard(mtx); 
     if(!refCount) 
     { 
      a.reset(new A); 
     } 
     ++refCount; 
    } 

    ~B() 
    { 
     std::cout << "~B() called" << std::endl; 
     std::lock_guard<std::mutex> guard(mtx); 
     --refCount; 
     if(!refCount) 
     { 
      a.reset(); 
     } 
    } 

    static std::unique_ptr<A> a; 
    static std::mutex mtx; 
    static int refCount; 
}; 

std::unique_ptr<A> B::a; 
int B::refCount(0); 
std::mutex B::mtx; 

int main() 
{ 
    { 
     B b1; //B::a should be created here 
     B b2; 
    } //B::a should be destroyed here 

    B b3; // B::a should be recreated here 
} //B::a should be destroyed again here 

http://coliru.stacked-crooked.com/a/fea428254933ee5c

私の質問も参照してください:代替(!スレッドセーフ)実装は参照カウントせずにありますか?これはおそらくstd::shared_ptrstd::weak_ptrの構成で解決することが可能でしょうか?

+0

を、それが、トラブルを要求します'struct B'のコピーコンストラクタとコピー代入(refcountが常に正しく維持されるように) – Leon

+0

'A'のインスタンスは、' B'のようなことが起こっていないときに実際には死ぬ必要がありますか?あなたが今、物事を持っている方法では、 '静的なA a; 'を単に持つことができ、それは' B'オブジェクトにしかアクセスできません。あなたの現在のコードでは、 'std :: unique_ptr'はref-countが0になったときにその内容を手動で削除しなければならないので、冗長です。 – Galik

+0

@レーオン:はい、それは最小限の例にちょうど短縮されました – meddle0106

答えて

1

はソリューションが欲しかったです:あなたの例と同じ出力生成

#include <memory> 
#include <iostream> 
#include <mutex> 
using std::shared_ptr; 
using std::weak_ptr; 

struct A 
{ 
    A() { std::cout << "A() called" << std::endl; } 
    ~A() { std::cout << "~A() called" << std::endl; } 
}; 

struct B 
{ 
    B() 
    { std::cout << "B() called" << std::endl; 
     std::lock_guard<std::mutex> guard(mtx); 
     if (!(ac =aw.lock())) 
      aw =ac =shared_ptr<A>(new A); 
    } 

    ~B() 
    { std::cout << "~B() called" << std::endl; 
    } 
    shared_ptr<A> ac; 
    static weak_ptr<A> aw; 
    static std::mutex mtx; 
}; 
weak_ptr<A> B::aw; 
std::mutex B::mtx; 

int main() 
{ 
    { 
     B b1; //B::a should be created here 
     B b2; 
    } //B::a should be destroyed here 

    B b3; // B::a should be recreated here 
} //B::a should be destroyed again here 

:それはの適切な実施を逃すので、このコードは意図的に短縮された場合を除き

B() called 
A() called 
B() called 
~B() called 
~B() called 
~A() called 
B() called 
A() called 
~B() called 
~A() called 
4

Bのオブジェクトが存続している限り、オブジェクトが確実に存在することを保証する唯一の方法は、Bのオブジェクトを参照することです。実際に生きているかどうかを知る唯一の現実的な方法は、プログラムが実行されるときに任意に作成され破壊される場合です。

std::shared_ptrは内部的にrefcountを保持し、これらは原子的に追跡されます。手動でrefcountを手動で管理するのではなく、これらを使用する方が良いでしょう。 RAIIコンストラクタのすべてを細心の注意を払って実装する必要はありません。ここで