Связанный список 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_ptr
s.