Почему мой узел класса перезаписывает себя, а не создает новый объект узла - PullRequest
2 голосов
/ 05 октября 2019

может кто-нибудь запустить этот код и сказать мне, почему узел во вставке продолжает перезаписывать?

#ifndef LinkedList_hpp
#define LinkedList_hpp

#include <stdio.h>
#include <utility>

template<class T>class LinkedList{
public:
LinkedList(){
        head = nullptr;
        tail = nullptr;
        size = 0;
    }
    //void insert(T val);
    class Node{
        public:
        Node* next;
        T* value;
        Node* prev;
        Node(T* value){
            this->value = value;
        }
        Node(){
        }
        Node(T* value,Node* prev, Node* next){
            this->value = value;
            this->next = next;
            this->prev = prev;
        }
        Node* operator=(const Node& node){
            this->value = node.value;
            this->prev = node.prev;
            this->next = node.next;
            return *this;
        }

    };
public:
    Node* head;
    Node* tail;
    int size;
    void insert(T val){

в этой строке, если предыдущий заголовок был 10, текущий val, 40, перезаписывает старое значение заголовка и вставляет новый узел с val 40

        Node* temp = new Node(&val);
        if(head==nullptr){
            head = temp;
            tail = temp;
        }else{
            temp->next = head;
            head->prev = temp;
            head = temp;
        }
        size++;
    }
#endif

#include <iostream>
#include "LinkedList.hpp"

int main(int argc, const char * argv[]) {

   // LinkedList<int> t;
    int h = 7;
    int j = 10;
    int k = 40;
    LinkedList<int>* list1 = new LinkedList<int>();


    list1->insert(h);
    list1->insert(j);
    list1->insert(k);

return 0;
}

каждый развызывается insert и создается новый узел, он перезаписывает старое значение и все становится текущим Val

Ответы [ 2 ]

2 голосов
/ 05 октября 2019
void insert(T val){

val является параметром для этой функции. Этот объект, этот val, существует только до возврата этой функции. В этот момент он уничтожается, как и все остальное, объявленное в нестатической области видимости внутри функции. Вот как работает C ++. Как только insert() возвращается, этого val больше нет. Перестает существоватьИдет навстречу своему создателю. Он становится бывшим объектом, который больше не существует и полностью находится в прошлом.

Ваша insert() функция выполняет следующее:

Node* temp = new Node(&val);

Вы передаете указатель на этоval параметр для конструктора Node, а Node затем сохраняет указатель на параметр в insert() как собственный член класса.

Это замечательно, но как только insert()возвращает, сохраненный указатель в new -ed Node становится указателем на уничтоженный объект, а разыменование этого указателя становится неопределенным поведением.

Затем вы пытаетесь разыменовать исходный указатель,который больше не указывает на действительный объект.

Это объясняет наблюдаемое неопределенное поведение в вашем коде.

Суть в том, что дизайн ваших классов и шаблонов в корне ошибочен. Для Node нет очевидной цели использовать указатель. Node должен просто хранить T как своего собственного члена класса, как value, вместо value, являющегося указателем на какой-то другой T, который существует где-то, и может быть уничтожен в любое время, что не являетсяпод управлением Node.

Другая проблема в показанном коде состоит в том, что двум конструкторам Node не удалось инициализировать указатели next и prev в NULL. Это также приведет к неопределенному поведению.

1 голос
/ 05 октября 2019
void insert(T val)

принимает аргументы по значению, поэтому val является локальной копией, а не оригиналом.

Node* temp = new Node(&val);

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

Решение:

Умный способ: хранить Node::value напрямую, а не в качестве указателя, который необходимо поддерживать в живых вместе сузел. Гораздо меньше управления памятью таким образом.

T* value;

становится

T value;

и

Node(T* value){
    this->value = value;
}

становится

Node(T value){
        this->value = value;
}

Другие виды использованияvalue должно быть соответственно обновлено. В общем, new - это такая головная боль, что следует использовать экономно .

Глупый путь: пройти по ссылке

void insert(T &val)

, чтобы указатель указывал начем дольше жил оригинал.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...