2016-05-30 4 views
1

グラフのノードを格納するshared_ptrを使用するプログラムを作成しました。各ノードには、それが属するノードにshared_ptrを保持する別のオブジェクトが関連付けられています。親の子のshared_ptrがスタックされているため、これを行う適切な方法ではないようです(構築後に親のshared_ptrsをさらに作成するとuse_count()が増加しません)。同じオブジェクトへの複数のshared_ptrs、1つが破損しました

ideone demo

親:

struct Parent : public enable_shared_from_this<Parent> 
{ 
    Child myChild; 

    Parent() : 
     myChild(shared_ptr<Parent>(this)) // can't use getptr() here -> bad_weak_ptr 
    {} 


    shared_ptr<Parent> getptr() 
    { 
     return shared_from_this(); 
    } 
}; 

子:

struct Child 
{ 
    shared_ptr<Parent> ptr; 

    Child(shared_ptr<Parent> a) : 
     ptr(a) 
    {} 
}; 

テスト:

shared_ptr<Parent> p(new Parent); 
cout << "UC of parent: " << p.use_count() << endl; 
cout << "UC of child ptr: " << p->myChild.ptr.use_count() << endl; 

shared_ptr<Parent> p2(p); 
cout << "UC of parent: " << p2.use_count() << endl; 
cout << "UC of child ptr: " << p2->myChild.ptr.use_count() << endl; 

出力:

UC of parent: 1 
UC of child ptr: 1 
UC of parent: 2 
UC of child ptr: 1 // expected 2! 

通常のctor(新規ではありません)からParentを作成し、getptr()でshared_ptrを取得すると、すべてが正常に動作することに気付きました。誰かがこれについて詳しく説明できますか?私は何か愚かなことをしていますか?

ありがとうございます!

+0

確かに 'this'ではなくshared_from_this()を子に渡したいと思いますか? – kfsone

+0

shared_from_this()が動作するためには、オブジェクトのshared_ptrが存在しなければならないので、bad_weak_ptr例外が発生します。 shared_ptr(this)を子に渡そうとしましたが、結果は同じです。 – Managarm

+2

親が死ぬまで(親の* member *)子が死ぬことはないため、子は親への所有権(シュレッド)ポインタを持つべきではありません。 * reference *を子の親に渡す(そして格納する)必要があります。 – Galik

答えて

2

問題は2つの異なるメモリコントロールブロックを作成したことです。 1つは、親オブジェクトへのshared_pointerを作成し、を呼び出す代わりにnewedポインタを使用してshared_pointerを手動で作成し、既存のコントロールブロックを再利用するshared_from_thisを呼び出すことによって、 Coliru

#include <iostream> 
#include <memory> 

using namespace std; 

struct Parent; 

struct Child 
{ 
    shared_ptr<Parent> ptr; 

    Child(Parent* a) : 
     ptr(a) 
    {} 
}; 

struct Parent : public enable_shared_from_this<Parent> 
{ 
    Child myChild; 

    Parent() : 
     myChild(this) 
    {} 


    shared_ptr<Parent> getptr() 
    { 
     return shared_from_this(); 
    } 
}; 

int main() 
{ 
    shared_ptr<Parent> p = (new Parent)->getptr(); // <-- The mistake was not using shared_from_this here, this creating 2 unrelated use counts for the same object 
    cout << "UC of parent: " << p.use_count() << endl; 
    cout << "UC of child ptr: " << p->myChild.ptr.use_count() << endl; 

    shared_ptr<Parent> p2(p); 
    cout << "UC of parent: " << p2.use_count() << endl; 
    cout << "UC of child ptr: " << p2->myChild.ptr.use_count() << endl; 
    return 0; 
} 

出力がある:あなたの数は1と1の両方だったshared_ptr<Parent> p(new Parent);あなたは2を共有しているため、それが2となっている必要があります。この間違いのため

g++ -std=c++14 main.cpp && ./a.out 
UC of parent: 2 
UC of child ptr: 2 
UC of parent: 3 
UC of child ptr: 3 

あなたの最初の手がかりは、後にすることをされている必要があります1つの親オブジェクトへのポインタ。

P.S:これは、私があなたが達成しようとしているもののための最良のデザインであるかどうかはわかりませんが、それは全く別の質問/議論です。

+0

Borgleaderが言っていることのMCVE:http://ideone.com/YGjLWD – kfsone

+0

ありがとう、今は明らかです! – Managarm

関連する問題