2017-09-27 2 views
0

Ich habe eine shared_ptr<Tree> tree und eine shared_ptr<TreeNode> node, die eine Liste von Kindern als geteilte Zeiger enthält.kopiere Objekt hinter einem geteilten Zeiger, der eine Liste von geteilten Zeigern enthält

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; 

    ... 

Ein Tree muss nur einen TreeNode als Root erhalten.

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

so dass Unterbaum erstellen Ich versuche, einen TreeNode zu bekommen und damit den Baum Konstruktor aufrufen.

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

Nun ist die Wurzel von newTree ist treeNode. Aber das Problem ist, dass jeder TreeNode auf seinen Eltern verweist. So auch treeNode.

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

Wenn, indem Sie durch die Eltern jedes TreeNode in newTree die Wurzel zu berechnen, werden wir einen anderen Wurzelknoten als newTreeNode, erreichen, weil newTreeNode selbst ein Elternteil hat.

Das Löschen dieses Parents ist keine Lösung, da das Objekt freigegeben ist und wir es in der ursprünglichen Struktur benötigen. Die einzige Lösung, die ich sehe, ist, den TreeNode zu kopieren und alle seine Mitglieder zu kopieren.

Wie kann ich das tun?

Basierend auf andere Antworten auf SO habe ich versucht, dies:

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

aber immer noch die Eltern der Berechnung wird auf den ursprünglichen Wurzelknoten führen. Daher konnte ich keinen Unterbaum erstellen.

Ich habe das Gefühl, dass es falsch ist shared_ptr für Tree und TreeNode zu verwenden, aber es ist nicht mein Code. Ich muss nur ein Feature hinzufügen.

+0

Ihr Klon sollte eine tiefe Kopie erstellen: Erstellen Sie einen neuen Knoten und klonen Sie jedes Kind. – Jarod42

+0

Da Ihr Titel das Wort "kopieren" enthält, gehen die Antworten, die Sie bisher angenommen haben, davon aus, dass Sie eine Kopie wünschen. In anderen Fällen könnte der Unterbaum auch auf einen Baum verweisen, der aus einigen der vorhandenen Knoten besteht (wie eine gefilterte Version des vorhandenen Baums). Diese Art von Teilbaum würde von dem gemeinsamen Zeiger auf den Vektor von Kindern profitieren. Das ist ein Grund dafür, Shared Pointer zu verwenden, aber wenn das keine Voraussetzung ist, würde ich zustimmen, dass shared_ptrs seltsam aussehen. – ROX

+0

Ich denke, ich würde diese Art von Teilbaum bevorzugen. Aber ich hätte ein Problem mit der Elternsache. Irgendwo in den Code-Knoten müssen die Eltern durchlaufen werden. Dann würde man zum ursprünglichen Wurzelknoten gehen. – Sadik

Antwort

1

Der gesamte Unterbaum geklont werden muss, nicht nur die Unter Wurzel. Da keiner der Zeiger kopiert wird, ist es nicht sinnvoll, den Klon zu initialisieren. Außerdem sollten Sie leere Zeiger auf zugewiesenen Speicher vermeiden, um eine starke Ausnahmesicherheit zu gewährleisten.

Ungeprüfte Beispiel:

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; 
} 

Ich habe das Gefühl, dass es falsch ist shared_ptr zu verwenden für Tree und TreeNode

ich Aktien Ihr Gefühl. Sicher, wenn die Knoten einen Elternzeiger haben, ist es unklar, wie die Knoten vernünftig über mehrere Bäume verteilt werden könnten.

std::shared_ptr<std::vector<std::shared_ptr<TreeEdge>>> scheint auch übermäßige Indirektion.

+0

Sie vergessen, Eltern der neuen Kinder festzulegen. – Jarod42

+0

@ Jarod42 guter Punkt; fügte hinzu, dass. – user2079303

+0

danke, das hat mir wirklich geholfen – Sadik

0

Ihre Klon-Funktion sollte wie etwas wie folgt aussehen:

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

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