Zuweisungsoperator in verkettete Liste C++

Ich versuche zu implementieren, verknüpfte Liste in c++.

Ich setze meine Zuweisungsoperator wie diese:

//assignment operator
template<class T>
LinkedList<T>& LinkedList<T>::operator = (const LinkedList& rhs) {

if (&rhs != this) {
    Node *tmp = head;

    while (tmp -> next) {
        head = head -> next;
        delete tmp;
        tmp = head;
    }

    tmp = rhs -> head;

    while (tmp) {
        append(tmp);
        tmp = tmp -> next;
    }
}

    return *this;
}

In der main-Funktion verwenden Sie den folgenden code zu testen:

LinkedList<int> *lst1 = new LinkedList<int>(7);

LinkedList<int> *lst2 = new LinkedList<int>(101);

std::cout << lst1 -> head -> data << std::endl;
std::cout << lst2 -> head -> data << std::endl;

lst1 = lst2;

std::cout << lst1 -> head -> data << std::endl;

delete lst1;
delete lst2;            <--------------- error here

Als ich erwarten, die Konsole Ausgänge:

7 101 101

Aber wenn das Programm zu löschen versuchen, lst2, bekomme ich eine Fehlermeldung:

Zeiger freigegeben wird nicht reserviert wurde

Ich benutze debugger und finden Sie heraus, wenn die Programm-Zuordnung:

lst1 = lst2;

lst1 ist eigentlich die Bezugnahme auf die Adresse, die Punkte lst2, anstatt eine Kopie der lst2 ist, also wenn ich löschen lst1, lst2 ist schon Weg.

So kann jemand mir bitte sagen, was falsch ist mit meinem Zuweisungsoperator?

Tut mir Leid wenn das eine Anfänger-Frage, aber ich verbrachte ein paar Stunden und konnte nicht herausfinden.

Meine fertige code ist im folgenden dargestellt:

template<class T>
class LinkedList {

private:
    class Node {
    public:
        T data;
        Node *next;

        //default constructor
        Node() = default;

        //constructor with data
        Node(const T& data) : data(data), next(NULL) {}

    };

public:
    Node *head;

    LinkedList(const LinkedList& copyLst);
    LinkedList& operator=(const LinkedList& byValList);
    LinkedList() : head(NULL){}
    LinkedList(Node *newNode) : head(newNode) {}
    LinkedList(T val) {
        head = new Node(val);
    }
    ~LinkedList();

    static LinkedList<int> sumLists(const LinkedList<int>& lst1, const LinkedList<int>& lst2) ;

    void insertAtFront(T val);
    void insertAtEnd(T val);
    void printList();
    void insert(T val);

    void append(const Node&);
};

//copy constructor
template<class T>
LinkedList<T>::LinkedList(const LinkedList<T>& copyLst) {

    const Node *cpCurrent = copyLst.head;
    Node *lsCurrent = NULL;

    if (cpCurrent != NULL) {
        head = new Node(cpCurrent -> data);
        lsCurrent = head;

        cpCurrent = cpCurrent -> next;

    }

    while (cpCurrent != NULL) {
        Node *newNode = new Node(cpCurrent -> data);
        lsCurrent -> next = newNode;

        lsCurrent = lsCurrent -> next;
        cpCurrent = cpCurrent -> next;
    }
}

//assignment operator
template<class T>
LinkedList<T>& LinkedList<T>::operator = (const LinkedList& rhs) {

    if (&rhs != this) {
        Node *tmp = head;

        while (tmp -> next) {
            head = head -> next;
            delete tmp;
            tmp = head;
        }

        tmp = rhs -> head;

        while (tmp) {
            append(tmp);
            tmp = tmp -> next;
        }
    }

    return *this;
}

//destructor
template<class T>
LinkedList<T>::~LinkedList() {
    Node *current = head;

    while (current != NULL) {
        head = head -> next;
        delete current;
        current = head;
    }
}

template<typename T>
void LinkedList<T>::append(const Node& node ){

    if (NULL == head) {
        Node *newNode = new Node(node -> data);
        head = newNode;
    } else {
        Node *current = head;

        while (current -> next) {
            current = current -> next;
        }


        Node *newNode = new Node(node -> data);
        current -> next = newNode;
    }
}
  • Das ist kein Konstruktor. Es ist ein Zuweisungsoperator. Beide Parteien (LS und RS) bereits konstruiert. Und lst1 = lst2; nicht brennen jede der code-unabhängig. Es ist eine einfache Zuordnung der ein Zeiger zu einem anderen, mit den unglücklichen Nebeneffekt lecken die Erinnerung, die Sie gerade zugewiesen lst1. I. e., Sie löschen die gleiche Liste zweimal, und leckt die anderen. Warum sind Sie die dynamische Zuordnung entweder in den ersten Platz?
  • verwenden *lst1 = *lst2; zum aufrufen Ihrer Zuweisungs-operator
  • Auch in Ihrer Zuweisungs-operator, die Sie vernachlässigen, um zu überprüfen, ob head NULL ist; wenn es ist, dass Sie nicht definiertes Verhalten, und wenn nicht, du Leck den letzten Knoten.
  • Danke für Eure Hilfe Jungs. Ich fand es heraus. 🙂
  • Zusätzlich zu dem, was Beta sagt über das auslassen der Ziel-Liste ist head Knoten, Sie sind auch nicht Durchlaufen der Ziel-Liste, Knoten korrekt, wenn Sie, befreien Sie, entweder. Die erste Schleife sollte eher so: while (head) { Node *tmp = head->next; delete head; head = tmp; } Und Ihre Kopie Konstruktor nicht die Initialisierung head wenn copyLst.head NULL ist.
  • Erzählen Sie mir, wenn ich so genannte copy-and-swap-idiom in meinem Zuweisungsoperator? sollte ich es nutzen für alle mit dem Zuweisungsoperator?
  • Do you mind telling me if I can use so-called copy-and-swap idiom Hat Ihr copy-Konstruktor arbeiten? Hat Ihr Destruktor Arbeit? Wenn beide Antworten "ja" ist, dann verwenden Sie die kopieren / tauschen und Graben alle, dass code in Ihrem Zuweisungsoperator.
  • Quelle-Objekt, das an einem copy-Konstruktor oder copy-Zuweisungsoperator ist in der Regel (und sollen) const, so dass Sie nicht swap direkt mit ihm. Aber Sie können kopieren Sie in ein temp-Objekt, und klicken Sie dann swap mit der temp. Das ist nicht ungewöhnlich, dass die Umsetzung idiom.

InformationsquelleAutor | 2015-06-16
Schreibe einen Kommentar