Связанный список C++ не будет работать так, как я ожидал (Smart Pointers)

#include <iostream>
#include <memory>

using namespace std;


class Node
{

//Private variables.
private:
    std::unique_ptr<Node> next; //Next node.
    std::unique_ptr<Node> prev; //Previous node.


    //Int value.
    int value;



//Public variables.
public:

    //Constructor.
    Node(int v)
    :next(nullptr), prev(nullptr), value(v)
    {
    }


    //Set next node.
    void set_next(std::unique_ptr<Node> new_node)
    {
       next = std::move(new_node);
    }


    //Set previous node.
    void set_prev(std::unique_ptr<Node> new_node)
    {
        prev = std::move(new_node);
    }


    //Set value.
    void set_value(int v)
    {
        value = v;
    }


    //Get next node.
    std::unique_ptr<Node> get_next()
    {
        return std::move(next);
    }


    //Get previous node.
    std::unique_ptr<Node> get_prev()
    {
        return std::move(prev);
    }


    //Get value.
    int get_value()
    {
        return value;
    }



};


class LinkedList
{

//Private variables.
private:
    std::unique_ptr<Node> head;
    std::unique_ptr<Node> tail;



//Public variables.
public:

    //Constructor.
    LinkedList()
    :head(nullptr), tail(nullptr)
    {
    }


    //Append a item to the list.
    void append(int v)
    {

        //Creating a new node.
        std::unique_ptr<Node> new_node( new Node(v) );


        //If this is the very first node.
        if (head == nullptr || tail == nullptr)
            {
                head = std::move(new_node);
                tail = std::move(new_node);
            }



        //Append.
        else
            {
                tail -> set_next( std::move(new_node) ); //Linking the new node.
                new_node -> set_prev( std::move(tail) ); //Set the previous.
                tail = std::move(new_node);              //Update the tail.
            }

    }


    //Print all the elements.
    void print()
    {

        //Starting node.
        std::unique_ptr<Node>curr = std::move(head);


        //While Loop.
        while(curr != nullptr)
            {
                cout << curr -> get_value() << endl;
                curr = std::move( curr -> get_next() );
            }
    }

};


int main()
{
LinkedList myList;

myList.append(1);
myList.append(2);
myList.append(3);
myList.append(4);

myList.print();

return 0;
}

Я должен видеть на выходе 1,2,3,4, но вместо этого я вижу только 4! Я сделал отладку, и я обнаружил, что следующий оператор выполняется 4 раза:

            //If this is the very first node.
        if (head == nullptr || tail == nullptr)
            {
                head = std::move(new_node);
                tail = std::move(new_node);
            }

Но почему работает 4 раза? В первый раз голова и хвост будут нулевыми, но после этого они будут указывать куда-то, так что это утверждение никогда не должно выполняться снова.

Я новичок в умных указателях, поэтому думаю, что мне там не хватает.

1 ответ

Одно фундаментальное свойство std::unique_ptr это только один std::unique_ptr может иметь данный указатель одновременно. Это то, что является "уникальной" частью.

std::unique_ptr<Node> new_node( new Node(v) );

Хорошо. Все идет нормально.

   head = std::move(new_node);
   tail = std::move(new_node);

И это твоя проблема. Вы пытаетесь двигаться так же std::unique_ptr на две другие. Это не сработает. Только один из них может иметь указатель.

Замените все ваши std::unique_ptrс std::shared_ptrs.

Другие вопросы по тегам