2017-09-27 5 views
0

共有ポインターとして子リストを含むshared_ptr<Tree> treeshared_ptr<TreeNode> nodeがあります。共有オブジェクトポインタの後ろのコピーオブジェクト

class TreeNode 
{ 
protected: 
    std::weak_ptr<TreeNode> parent; 

    /** 
    A list containing the children of this node 
    */ 
    std::shared_ptr<std::vector<std::shared_ptr<TreeEdge>>> children; 

    ... 

AツリーはそのルートとしてのTreeNodeを付与する必要があります。

Tree::Tree(const shared_ptr<TreeNode> root) 
    : root(root) 
{} 

したがって、そのサブツリーを作成するには、私はTreeNodeを取得し、それを使ってTreeコンストラクタを呼び出します。

shared_ptr<TreeNode> treeNode = oldTree->getASpecialNode(); 
shared_ptr<Tree> newTree = make_shared<Tree>(treeNode); 

newTreeのルートはtreeNodeです。しかし、問題は、すべてのTreeNodeがその親を指していることです。それでtreeNodeもそうです。 newTree内の任意のTreeNodeの両親を経てルートを計算する場合newTreeNode自身が親を持っているので

weak_ptr<TreeNode> TreeNode::getParent() const 
{ 
    return parent; 
} 

、我々は、newTreeNodeとは異なるルート・ノードに到達します。

オブジェクトが共有されているため、その親を削除することは解決できません。元のツリーにそのオブジェクトが必要になるためです。だから、私が見る唯一の解決策は、TreeNodeをコピーして、それがすべてのメンバーをコピーすることです。

どうすればいいですか?

std::shared_ptr<TreeNode> TreeNode::clone() const 
{ 
    auto clone = new TreeNode (*this); 
    clone->setParent(weak_ptr<TreeNode>()); 
    return shared_ptr<TreeNode>(clone); 
} 

しかし、まだ両親を計算すると、元のルートノードにつながる:SO私はこれを試した上で、他の回答に基づいて

。だから私はサブツリーを作ることができませんでした。

TreeTreeNodeshared_ptrを使用するのは間違っていると感じましたが、それは自分のコードではありません。私は機能を追加するだけです。サブツリー全体を複製する必要があります

std::shared_ptr<TreeNode> TreeNode::clone() const 
{ 
    auto res = std::make_shared<TreeNode>(); 

    for (auto child : *children) { 
     res->AddChild(child->clone()); 
    } 
    return res; 
} 
+0

クローンは完全なコピーを作成する必要があります。新しいノードを作成し、各子をクローンします。 – Jarod42

+0

あなたのタイトルには「コピー」という単語が含まれているので、これまでの回答ではコピーが必要です。他の場合には、サブツリーは、既存のツリーのフィルタリングされたバージョンのような、いくつかの既存のノードからなるツリーを参照することもできる。そのような種類のサブツリーは、子どものベクトルへの共有ポインタから利益を得ます。だからそれが共有ポインタを使う理由ですが、それが要件でないならば、shared_ptrsは奇妙に見えることに同意します。 – ROX

+0

私はそのような種類のサブツリーを好むと思います。しかし、私は親のものに問題があります。コードノードのどこかで、親を通して移動する必要があります。次に、元のルートノードに移動します。 – Sadik

答えて

1

だけでなく、サブルート:

+0

新しい子の親を設定するのを忘れてしまいます。 – Jarod42

+0

@ Jarod42良い点;それを加えた。 – user2079303

+0

ありがとう、これは本当に私を助けた – Sadik

0

あなたのクローン機能は次のようなもののようになります。いずれのポインタもコピーされていないので、コピーを初期化することは有用ではない。また、強力な例外安全性を保証するために、割り当てられたメモリへのポインタを避けるべきです。

テストされていない例:

std::shared_ptr<TreeNode> TreeNode::clone() const 
{ 
    auto clone = std::make_shared<TreeNode>(); 
    clone->children->reserve(children->size()); 
    for(const auto& c : *children) { 
     auto c_clone = c->clone(); 
     c_clone->setParent(clone); 
     clone->children->push_back(c_clone); 
    } 
    return clone; 
} 

は、私はそれがTreeTreeNode

I シェアあなたの気持ちのためshared_ptrを使用することが間違っているという感覚を持っています。確かに、ノードに親ポインタがある場合、どのようにノードが複数のツリーにわたって分かりやすく共有されるかは不明です。

std::shared_ptr<std::vector<std::shared_ptr<TreeEdge>>>も過度の間接的なようです。

関連する問題