2017-09-27 1 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; 

    ... 

트리는 루트로서 TreeNode가 주어져야합니다.

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

그래서 나는 TreeNode를 얻을 그것으로 트리의 생성자를 호출하려고하는 서브 트리를 만들 수 있습니다.

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

지금 newTree의 루트는 treeNode입니다. 하지만 문제는 모든 TreeNode가 부모를 가리키고 있다는 것입니다. treeNode도 마찬가지입니다. newTreeNode 자체가 부모를 가지고 있기 때문에

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

newTree의 모든의 TreeNode의 부모를 통과하여 루트를 계산

, 우리는 newTreeNode 아닌 다른 루트 노드에 도달합니다.

개체를 공유하고 원본 트리에서이 개체가 필요하므로 해당 부모를 삭제하는 것은 해결책이 아닙니다. 그래서 내가 볼 수있는 유일한 해결책은 TreeNode를 복사하고 모든 구성원을 복사하는 것입니다.

어떻게하면됩니까?

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

하지만 여전히 부모를 계산하는 것은 원래의 루트 노드로 이어질 것입니다 : 다른 답변을 바탕으로

그래서이 시도. 그래서 하위 트리를 만들 수 없었습니다.

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

제목에 "copy"라는 단어가 있기 때문에 지금까지 가지고있는 대답은 사본을 원한다고 합리적으로 추측합니다. 다른 경우 하위 트리는 기존 노드의 일부 (필터링 된 버전의 기존 트리)로 구성된 트리를 참조 할 수도 있습니다. 이러한 종류의 하위 트리는 자식 벡터에 대한 공유 포인터의 이점을 얻을 수 있습니다. 그래서 이것이 공유 포인터를 사용하는 이유입니다.하지만 이것이 요구 사항이 아니라면 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>>> 또한 과도한 간접적 인 것처럼 보입니다.