Вернуть вектор копий указанного значения unique_ptr - PullRequest
0 голосов
/ 30 июня 2018

Я пытаюсь реализовать два метода. У меня есть класс узла, который реализован так:

class Node
{
public:
    // A NodeMap is a std::map associating a node with its ID as a key, much faster for searching the Node than a simple vector
    using NodeMap = std::map<QString, std::unique_ptr<Node>>;

    Node();
    Node(const Vector3D &position);

    const Vector3D& getPosition() const;

    std::vector<Node*>& getLeaves() const;
    std::vector<Node>& getAbsoluteLeaves() const;

    bool hasChildren() const;

protected:
    Vector3D position_;
    NodeMap children_;
};

Я удалил все бесполезные вещи для этой проблемы. Моя проблема с методами getLeaves и getAbsoluteLeaves. Первый просто возвращает листья узла (дочерние элементы без дочерних элементов). Второй делает то же самое, за исключением того, что вычисляет абсолютную позицию. Я хочу, чтобы класс Node сохранял право собственности на детей. Возвращенные векторы предназначены только для просмотра значений узлов, они не будут изменены.

Это моя реализация первых методов

std::vector<Node*>& Node::getLeaves() const
{
    std::vector<Node*> leaves;

    for (const auto &child : children_) {
        if (child.second->hasChildren()) {
            std::vector<Node*> child_children(child.second->getLeaves());
            leaves.insert(leaves.end(), child_children.begin(), child_children.end());
        } else {
           leaves.push_back(child.second.get());
        }
    }

    return leaves;
}

Я возвращаю сюда вектор указателей, я читал, что это хорошая практика. Первый вопрос, придется ли мне вручную удалять указатели после их использования? Этот метод вызвал сбой программы без каких-либо сообщений, но он компилируется. Откуда может появиться ошибка? Как я могу найти это?

Вот реализация второго метода:

std::vector<Node>& Node::getAbsoluteLeaves() const
{
    std::vector<Node> leaves;

    for (auto child : children_) {
        if (child.second->hasChildren()) {
            std::vector<Node> child_children = child.second->getAbsoluteLeaves();
            leaves.insert(leaves.end(), child_children.begin(), child_children.end());
        } else {
            child.second->setPosition(child.second->getPosition() + position_); // Need to edit a copy of this node, not the original one!
            leaves.push_back(child.second.get());
        }
    }

    return leaves;
}

Этот не компилируется, и я знаю, почему, я должен сделать копию заостренного узла, чтобы вычислить абсолютную позицию, но я не могу сделать это с unique_ptr. Как мне решить эту проблему? Я действительно не знаю, как мне реализовать этот метод.

1 Ответ

0 голосов
/ 30 июня 2018

Для второй функции вы можете скопировать и сохранить узел, на который ссылается unique_ptr, следующим образом:

leaves.push_back(*child.second); // makes a copy
leaves.back().setPosition(child.second->getPosition() + position_);

Конечно, Node понадобится конструктор копирования. Из вашего вопроса не совсем понятно, как это будет выглядеть, потому что NodeMap не копируется (из-за содержания unique_ptrs).

...