Неявно скопированный конструктор Smart Pointers - PullRequest
0 голосов
/ 23 апреля 2020

У меня есть следующий код:

#include <vector>
#include <memory>

struct Node{
    int value;
    Node *left = nullptr;
    Node *right = nullptr;
};

std::vector<std::unique_ptr<Node>> createListNodes(int min, int max)
{
    // odered vector with i.e. {0,1,2,3,4}
    std::vector<std::unique_ptr<Node>> alternative;
    if (min == max)
    {
        alternative.emplace_back(std::make_unique<Node>(min,nullptr,nullptr)); // it is a leaf node
        return  alternative;
    }
    for (int i=min; i<=max; i++)
    {
        std::vector<std::unique_ptr<Node>> left = createListNodes(min,i-1); // for the left side
        std::vector<std::unique_ptr<Node>> right = createListNodes(i+1,max); // for the left side
        if (left.size() == 0) // if node i has just one child and it is in the right
        {
            for (auto elem_right : right) // ERROR
            {
                alternative.emplace_back(std::make_unique<Node>(i,nullptr,elem_right));
            }
        }
        else if (right.size() == 0) // if node i has just one child and it is in the left
        {
            for (auto elem_left : left) // ERROR
            {   
                alternative.emplace_back(std::make_unique<Node>(i,elem_left,nullptr));
            }
        }
        for (auto elem_left : left) // ERROR
        {
            for (auto elem_right : right) // ERROR
            {
                alternative.emplace_back(std::make_unique<Node>(i,elem_left,elem_right));
            }
        }
    }
    return alternative;

}

int main()
{
    int N = 4;
    std::vector<std::unique_ptr<Node>> combinations = createListNodes(0, N);
}

Я получаю сообщение об ошибке при итерации по вектору unique_ptr, но мне не удается понять реальную проблему. Я также попытался переместить unique_ptr в векторную альтернативу, но проблема все еще сохраняется.

error: call to implicitly-deleted copy constructor of 'std::__1::unique_ptr<Node,
      std::__1::default_delete<Node> >'
            for (auto elem_left : left)

1 Ответ

1 голос
/ 23 апреля 2020

Вы можете сделать что-то вроде:

У вас есть несколько проблем, вы перебираете копию вместо ссылки.

время жизни внутренних узлов останавливается на каждой итерации l oop.

Вы можете сделать узлы своими дочерними:

struct Node{
    int value;
    std::unique_ptr<Node> left = nullptr;
    std::unique_ptr<Node> right = nullptr;

    Node(int v, std::unique_ptr<Node> left = nullptr, std::unique_ptr<Node>right = nullptr) :
        value(v), left(std::move(left)), right(std::move(right))
    {}

    std::unique_ptr<Node> DeepCopy() const
    {
        return std::make_unique<Node>(value,
            left ? left->DeepCopy() : nullptr,
            right ? right->DeepCopy() : nullptr);
    }
};

std::vector<std::unique_ptr<Node>> createListNodes(int min, int max)
{
    // odered vector with i.e. {0,1,2,3,4}
    std::vector<std::unique_ptr<Node>> alternative;
    if (min == max)
    {
        alternative.emplace_back(std::make_unique<Node>(min, nullptr, nullptr)); // it is a leaf node
        return  alternative;
    }
    for (int i=min; i<=max; i++)
    {
        std::vector<std::unique_ptr<Node>> left = createListNodes(min, i-1); // for the left side
        std::vector<std::unique_ptr<Node>> right = createListNodes(i+1, max); // for the left side
        if (left.size() == 0) // if node i has just one child and it is in the right
        {
            for (auto& elem_right : right)
            {
                alternative.emplace_back(std::make_unique<Node>(i, nullptr, std::move(elem_right)));
            }
        }
        else if (right.size() == 0) // if node i has just one child and it is in the left
        {
            for (auto& elem_left : left)
            {   
                alternative.emplace_back(std::make_unique<Node>(i, std::move(elem_left), nullptr));
            }
        }
        for (auto& elem_left : left)
        {
            for (auto& elem_right : right)
            {
                alternative.emplace_back(std::make_unique<Node>(i, elem_left->DeepCopy(), elem_right->DeepCopy()));
            }
        }
    }
    return alternative;
}

Демо (с std::unique_ptr)

Демо (с std::shared_ptr)

...