C++ this-> Zeiger

Life Sucks

Cadet 2nd Year
Registriert
Juli 2018
Beiträge
29
Hallo,

ich habe folgende Aufgabe und komme gerade bei der Theorie nicht weiter. Also ich hab folgende Funktion:

void insertBack(List & _List);

So die Funktion soll die "_List" liste mit einer anderen Liste vereinen. Ich soll die _List liste an das ende einer anderen Liste hinzufügen.

Das this->head bezieht sich doch auf das "_List" also auf das head der liste _List oder liege ich da falsch??
 
Life Sucks schrieb:
Das this->head bezieht sich doch auf das "_List" also auf das head der liste _List oder liege ich da falsch??
this->head ist die Variable head in der aktuellen Instanz der Klasse in der dieser Ausdruck steht. Das was du beschreibst ist _List.head und das ist nicht gleich this->head, sofern dieser Ausdruck in void List::insertBack(List& _List); steht.

Gruß
BlackMark
 
  • Gefällt mir
Reaktionen: Revan1710
Dann hatte ich komplett in die falsche Richtung gedacht. Danke.
 
Etwas mehr Code als nur die Funktionsdeklaration wäre wohl hilfreich, ich glaube nämlich nicht, dass du mit head hier korrekt am Ende der Liste etwas anfügst

Zu deiner Verwirrung mit dem this pointer und um das von @BlackMark etwas zu verdeutlichen: Du hast ha vmtl etwas in der Art:

Code:
List list1;
List list2;

// füge list2 an list1 an
list1.insertBack(list2);

Innerhalb der Funktion bezieht sich this nun auf die aufrufende Instanz - also list1
 
Zuletzt bearbeitet:
@Revan1710 Es haben sich leider zwei kleine Fehler in deine Verdeutlichung geschlichen, die mitunter zu noch mehr Verwirrung führen könnten. Richtig wäre:
C++:
List list1;
List list2;

list1.insertBack(list2);

list1 ist kein Pointer, also braucht man den normalen member access operator. Und die Signatur von insertBack verlangt eine Referenz, keinen Pointer, also ohne address-of operator bei list2.

Gruß
BlackMark
 
  • Gefällt mir
Reaktionen: Revan1710
Jou hast natürlich absolut Recht, kommt davon, wenn man sowas schnell im Zug auf dem Smartphone macht kurz vor dem Aussteigen

Ich korrigier das noch, damit ich mich nicht schämen muss
 
Revan1710 schrieb:
Etwas mehr Code als nur die Funktionsdeklaration wäre wohl hilfreich, ich glaube nämlich nicht, dass du mit head hier korrekt am Ende der Liste etwas anfügst

Sorry mein Fehler ich habe einen "head_tail", sowohl Anfang als auch ende.
 
@Life Sucks Poste den gesamten Code. Verpack ihn schön in [CODE=cpp]...[/CODE], damit man ihn auch lesen kann, und dann stell weitere Fragen, falls es noch welche gibt.

Gruß
BlackMark
 
list.cpp:
C++:
#include "List.h"

List::List()
{
    // Konstruktor für eine leere Liste
    head_tail = new Node;
    list_size = 0;
    temp = false;
    head_tail->next = head_tail;
    head_tail->prev = head_tail;
}

List::List(const List & _List)
{
    // Konstruktor mit Übergabe einer Liste, die dann kopiert wird.
    // in dem Objekt _List sind die Knotenwerte enthalten, die Kopiert werden sollen.
    list_form = _List.list_form;
    head_tail = new Node;
    list_size = 0;
    temp = _List.temp;
    head_tail->next = head_tail;
    head_tail->prev = head_tail;
    Node * tmp_node;
    tmp_node = _List.head_tail->next;
    while (tmp_node != _List.head_tail)
    {
        head_tail->prev = new Node(tmp_node->key, head_tail->prev->next, head_tail->prev);
        head_tail->prev->prev->next = head_tail->prev;
        list_size++;
        tmp_node = tmp_node->next;
    }
    if (_List.temp) delete & _List;        // ist die Übergebene Liste eine temporäre Liste? -> aus Operator +
}

List::List(const List * _List)
{
    // Konstruktor mit Übergabe einer Liste, die dann kopiert wird.
    // in dem Objekt _List sind die Knotenwerte enthalten, die Kopiert werden sollen.
    list_form = _List->list_form;
    head_tail = new Node;
    list_size = 0;
    temp = _List->temp;
    head_tail->next = head_tail;
    head_tail->prev = head_tail;
    Node * tmp_node;
    tmp_node = _List->head_tail->next;
    while (tmp_node != _List->head_tail)
    {
        head_tail->prev = new Node(tmp_node->key, head_tail->prev->next, head_tail->prev);
        head_tail->prev->prev->next = head_tail->prev;
        list_size++;
        tmp_node = tmp_node->next;
    }
    if (_List->temp) delete _List;        // ist die Übergebene Liste eine temporäre Liste? -> aus Operator +
}

List::~List()
{
    // Dekonstruktor
    // Alle Knoten der Liste müssen gelöscht werden, wenn die Liste gelöscht wird.
    //hier alle Knoten löschen, die im Objekt List allokiert wurden
    if (head_tail->next == head_tail)
        delete head_tail;
    else
    {
        Node *ptr = head_tail->next;
        while (ptr != head_tail)
        {
            ptr = ptr->next;
            delete ptr->prev;
        }
        delete head_tail;
        ptr = nullptr;
    }

}

void List::insertFront(int key)
{
    // Einfügen eines neuen Knotens am Anfang der Liste
    //Einen neuen Knoten mit dem Schlüsselwert key am Anfang der Liste einfügen
    Node *new_node = new Node();
    new_node->key = key;
    new_node->next = nullptr;
    new_node->prev = nullptr;
    if (head_tail->next == head_tail && head_tail->prev == head_tail)
    {
        head_tail->next = new_node;
        head_tail->prev = new_node;
        new_node->prev = head_tail;
        new_node->next = head_tail;
    }
    else
    {
        head_tail->next->prev = new_node;
        new_node->prev = head_tail;
        new_node->next = head_tail->next;
        head_tail->next = new_node;
    }
    list_size++;
}

void List::insertFront(List & _List)
{
    // Einfügen einer vorhandenen Liste am Anfang
    /*
    Die einzufügenden Knoten werden übernommen (nicht kopiert)
    Die einzufügende Liste _List ist anschließend leer.
    Es darf keine Schleife und kein new benutzt werden.*/
    /*
        Es wird ein Objekt übergeben in dem Knoten vorhanden sein können.
        Diese Knoten (koplette Kette) werden an den Anfang der Liste (this) übertragen ohne sie zu kopieren!
    */
    
    //Wenn liste leer
    if (this->head_tail->next == this->head_tail && this->head_tail->prev == this->head_tail)
    {
        _List.head_tail->next->prev = this->head_tail;
        _List.head_tail->prev->next = this->head_tail->next;
        this->head_tail->next = _List.head_tail->next;
        this->head_tail->prev = _List.head_tail->prev;

        _List.head_tail->next = _List.head_tail;
        _List.head_tail->prev = _List.head_tail;
    }


    //Wenn liste voll:
    else
    {
        _List.head_tail->next->prev = this->head_tail;
        _List.head_tail->prev->next = this->head_tail->next;
        this->head_tail->next = _List.head_tail->next;

        _List.head_tail->next = _List.head_tail;
        _List.head_tail->prev = _List.head_tail;
    }
    
}

void List::insertFront(List * _List)
{
    // Einfügen einer vorhandenen Liste am Anfang
    /*
    Die einzufügenden Knoten werden übernommen (nicht kopiert)
    Die einzufügende Liste _List ist anschließend leer.
    Es darf keine Schleife und kein new benutzt werden.
    */
    /*
        Es wird ein Objekt übergeben in dem Knoten vorhanden sein können.
        Diese Knoten (koplette Kette) werden an den Anfang der Liste (this) übertragen ohne sie zu kopieren!
    */

    //Wenn liste leer
    if (this->head_tail->next == this->head_tail && this->head_tail->prev == this->head_tail)
    {
        _List->head_tail->next->prev = this->head_tail;
        _List->head_tail->prev->next = this->head_tail->next;
        this->head_tail->next = _List->head_tail->next;
        this->head_tail->prev = _List->head_tail->prev;

        _List->head_tail->next = _List->head_tail;
        _List->head_tail->prev = _List->head_tail;
    }


    //Wenn liste voll:
    else
    {
        _List->head_tail->next->prev = this->head_tail;
        _List->head_tail->prev->next = this->head_tail->next;
        this->head_tail->next = _List->head_tail->next;

        _List->head_tail->next = _List->head_tail;
        _List->head_tail->prev = _List->head_tail;
    }
}

void List::insertBack(int key)
{
    // Einfügen eines neuen Knotens am Ende der Liste
    //Einen neuen Knoten mit dem Schlüsselwert key am Ende der Liste einfügen
    Node *new_node = new Node();
    new_node->key = key;
    new_node->next = nullptr;
    new_node->prev = nullptr;
    if (head_tail->next == head_tail && head_tail->prev == head_tail)
    {
        head_tail->next = new_node;
        head_tail->prev = new_node;
        new_node->prev = head_tail;
        new_node->next = head_tail;
    }
    else
    {
        head_tail->prev->next = new_node;
        new_node->prev = head_tail->prev;
        head_tail->prev = new_node;
        new_node->next = head_tail;
    }
    list_size++;
}

void List::insertBack(List & _List)
{
    // Einfügen einer vorhandenen Liste am Ende
    /*
    Die einzufügenden Knoten werden übernommen (nicht kopiert)
    Die einzufügende Liste _List ist anschließend leer.
    Es darf keine Schleife und kein new benutzt werden.*/
    /*
        Es wird ein Objekt übergeben in dem Knoten vorhanden sein können.
        Diese Knoten (koplette Kette) werden an das Ende der Liste (this) angehangen ohne sie zu kopieren!
    */

    //Wenn Liste leer:
    if (this->head_tail->next == this->head_tail && this->head_tail->prev == this->head_tail)
    {
        _List.head_tail->prev->next = this->head_tail;
        this->head_tail->prev = _List.head_tail->prev;
        this->head_tail->next = _List.head_tail->next;
        _List.head_tail->next->prev = this->head_tail;

        _List.head_tail->next = _List.head_tail;
        _List.head_tail->prev = _List.head_tail;
    }
    else
    {
        this->head_tail->prev->next = _List.head_tail->next;
        _List.head_tail->next->prev = this->head_tail->prev;
        _List.head_tail->prev->next = this->head_tail;
        this->head_tail->prev = _List.head_tail->prev;
        

        _List.head_tail->next = _List.head_tail;
        _List.head_tail->prev = _List.head_tail;
    }
}

void List::insertBack(List * _List)
{
    // Einfügen einer vorhandenen Liste am Ende
    /*
    Die einzufügenden Knoten werden übernommen (nicht kopiert)
    Die einzufügende Liste _List ist anschließend leer.
    Es darf keine Schleife und kein new benutzt werden.*/
    /*
        Es wird ein Objekt übergeben in dem Knoten vorhanden sein können.
        Diese Knoten (koplette Kette) werden an das Ende der Liste (this) angehangen ohne sie zu kopieren!
    */

    if (this->head_tail->next == this->head_tail && this->head_tail->prev == this->head_tail)
    {
        _List->head_tail->prev->next = this->head_tail;
        this->head_tail->prev = _List->head_tail->prev;
        this->head_tail->next = _List->head_tail->next;
        _List->head_tail->next->prev = this->head_tail;

        _List->head_tail->next = _List->head_tail;
        _List->head_tail->prev = _List->head_tail;
    }
    else
    {
        this->head_tail->prev->next = _List->head_tail->next;
        _List->head_tail->next->prev = this->head_tail->prev;
        _List->head_tail->prev->next = this->head_tail;
        this->head_tail->prev = _List->head_tail->prev;


        _List->head_tail->next = _List->head_tail;
        _List->head_tail->prev = _List->head_tail;
    }
}

bool List::getFront(int & key)
{
    // entnehmen des Knotens am Anfang der Liste
    // der Wert wird als Parameter zurückgegeben
    // der Knoten wird entnommen
    /*
        Der Wert des vorderen Schlüsselknotens wird rückgegeben und der Knoten gelöscht.
        Die Methode del(key) darf nicht zum löschen benutzt werden.
    */

    if(head_tail->next == head_tail && head_tail->prev == head_tail)
        return false;

    else
    {
        Node *del = head_tail->next;
        key = del->key;
        head_tail->next->next->prev = head_tail;
        head_tail->next = head_tail->next->next;
        delete del;
    }
    return true;
}

bool List::getBack(int & key)
{    // entnehmen des Knotens am Ende der Liste
    // der Wert wird als Parameter zurückgegeben
    // der Knoten wird entnommen
    /*
        Der Wert des letzten Schlüsselknotens wird rückgegeben und der Knoten gelöscht.
        Die Methode del(key) darf nicht zum löschen benutzt werden.
    */
    if (head_tail->next == head_tail && head_tail->prev == head_tail)
        return false;

    else
    {
        Node *del = head_tail->prev;
        key = del->key;
        head_tail->prev->prev->next = head_tail;
        head_tail->prev = head_tail->prev->prev;
        delete del;
    }
}

bool List::del(int key)
{
    // Löschen eines gegebenen Knotens
    //Löschen des Knotens mit dem Schlüssel key
    Node *ptr = head_tail->next;
    while (ptr->key != key && ptr != head_tail)
        ptr = ptr->next;
    if (ptr->key == key)
    {
        if (ptr->next == head_tail && ptr->prev == head_tail)
        {
            delete ptr;
            head_tail->next = head_tail;
            head_tail->prev = head_tail;
        }
        else
        {
            ptr->prev->next = ptr->next;
            ptr->next->prev = ptr->prev;
        }
    }
    list_size--;
    return false;
}

bool List::search(int key)
{
    // suchen eines Knotens
    //suchen ob ein Knoten mit dem Schlüssel key existiert.
    Node *ptr = head_tail->next;
    while (ptr->key != key && ptr != head_tail)
        ptr = ptr->next;

    if (ptr->key == key)
        return true;

    return false;
}

bool List::swap(int key1, int key2)
{
    // Vertauschen von zwei Knoten
    // Dabei werden die Zeiger der Knoten und deren Nachbarn verändert.
    //Vertauschen von zwei Knoten mit dem key1 und dem key2
    //Es dürfen nicht nur einfach die Schlüssel in den Knoten getauscht werden!
    //Die Knoten sind in der Kette umzuhängen.
    if (head_tail->next == head_tail && head_tail->prev == head_tail)
        return false;
    else
    {
        int c1 = 0, c2 = 0;
        Node *ptr1 = head_tail->next, *ptr2 = head_tail->next, *tmp1 = head_tail->next, *tmp2 = head_tail->next;
        while(ptr1->key != key1 && ptr1 != head_tail) { ptr1 = ptr1->next; c1++; }
        while(ptr2->key != key2 && ptr2 != head_tail) { ptr2 = ptr2->next; c2++; }
        if (ptr1->key == key1 && ptr2->key == key2)
        {
            if (c1 < c2)
            {
                if (ptr1->next->next != ptr2)
                {
                    tmp1 = ptr1->next; tmp2 = ptr2->prev;

                    ptr1->prev->next = ptr2;
                    ptr2->prev = ptr1->prev;
                    ptr1->next = ptr2->next;
                    ptr2->next->prev = ptr1;
                    ptr2->next = tmp1;
                    ptr1->prev = tmp2;
                }
                else if (ptr1->next->next == ptr2)
                {
                    tmp1 = ptr1->next;

                    ptr1->prev->next = ptr2;
                    ptr2->prev = ptr1->prev;
                    ptr1->next = ptr2->next;
                    ptr2->next->prev = ptr1;
                    ptr2->next = tmp1;
                    ptr1->prev = tmp1;
                }
                else if (ptr1->next == ptr2)
                {
                    ptr1->prev->next = ptr2;
                    ptr2->prev = ptr1->prev;
                    ptr1->next = ptr2->next;
                    ptr2->next->prev = ptr1;
                    ptr2->next = ptr1;
                    ptr1->prev = ptr2;
                }
            }
            else if (c1 > c2)
            {
                if (ptr2->next->next != ptr1)
                {
                    tmp1 = ptr1->prev; tmp2 = ptr2->next;

                    ptr2->prev->next = ptr1;
                    ptr1->prev = ptr2->prev;
                    ptr2->next = ptr1->next;
                    ptr1->next->prev = ptr2;
                    ptr1->next = tmp2;
                    ptr2->prev = tmp1;
                }
                else if (ptr2->next->next == ptr1)
                {
                    tmp2 = ptr2->next;

                    ptr2->prev->next = ptr1;
                    ptr1->prev = ptr2->prev;
                    ptr2->next = ptr1->next;
                    ptr1->next->prev = ptr2;
                    ptr1->next = tmp2;
                    ptr2->prev = tmp2;
                }
                else if (ptr2->next == ptr2)
                {
                    ptr2->prev->next = ptr1;
                    ptr1->prev = ptr2->prev;
                    ptr2->next = ptr1->next;
                    ptr1->next->prev = ptr2;
                    ptr1->next = ptr2;
                    ptr2->prev = ptr1;
                }
            }
            else return false;
        }
        else return false;
    }
    return true;
}

int List::size(void)
{
    // Rückgabe der Knoten in der Liste mit O(1)
    //Anzahl der Knoten in der Liste zurückgeben.
    Node *ptr = head_tail;
    int lenght = 0;
    while (ptr->next != head_tail) { ptr = ptr->next; lenght++; }
    return lenght;
    //return list_size;
}

bool List::test(void)
{
    // Testmethode: die Methode durchläuft die Liste vom Anfang bis zum Ende und zurück
    // Es werden dabei die Anzahl der Knoten gezählt.
    // Stimmt die Anzahl der Knoten überein liefert die Methode true
    Node * tmp = head_tail->next;
    int i_next = 0, i_prev = 0;
    while (tmp != head_tail) {
        tmp = tmp->next;
        if (i_next > list_size) return false;
        i_next++;
    }
    if (i_next != list_size) return false;
    tmp = head_tail->prev;
    while (tmp != head_tail) {
        tmp = tmp->prev;
        if (i_prev > list_size) return false;
        i_prev++;
    }
    return i_prev == i_next;
}

List & List::operator = (const List & _List)
{
    // in dem Objekt _List sind die Knotenwerte enthalten, die Kopiert werden sollen.
    // Kopiert wird in das Objekt "this"
    if (this == &_List) return *this;        //  !! keine Aktion notwendig
    list_form = _List.list_form;
    Node * tmp_node;
    if (list_size)
    {
        Node * tmp_del;
        tmp_node = head_tail->next;
        while (tmp_node != head_tail)        // Alle eventuell vorhandenen Knoten in this löschen
        {
            tmp_del = tmp_node;
            tmp_node = tmp_node->next;
            delete tmp_del;
        }
        list_size = 0;
        head_tail->next = head_tail;
        head_tail->prev = head_tail;
    }
    tmp_node = _List.head_tail->next;        // Die Listen-Knotenwerte werden kopiert
    while (tmp_node != _List.head_tail)
    {
        insertBack(tmp_node->key);
        tmp_node = tmp_node->next;
    }
    if (_List.temp) delete & _List;            // ist die Übergebene Liste eine temporäre Liste? -> aus Operator +
    return *this;
}

List & List::operator = (const List * _List)
{
    // in dem Objekt _List sind die Knotenwerte enthalten, die Kopiert werden sollen.
    // Kopiert wird in das Objekt "this"
    if (this == _List) return *this;        //  !! keine Aktion notwendig
    list_form = _List->list_form;
    Node * tmp_node;
    if (list_size)
    {
        Node * tmp_del;
        tmp_node = head_tail->next;
        while (tmp_node != head_tail)        // Alle eventuell vorhandenen Knoten in this löschen
        {
            tmp_del = tmp_node;
            tmp_node = tmp_node->next;
            delete tmp_del;
        }
        list_size = 0;
        head_tail->next = head_tail;
        head_tail->prev = head_tail;
    }
    tmp_node = _List->head_tail->next;
    while (tmp_node != _List->head_tail)    // Die Listen-Knotenwerte werden kopiert
    {
        insertBack(tmp_node->key);
        tmp_node = tmp_node->next;
    }
    if (_List->temp) delete _List;            // ist die Übergebene Liste eine temporäre Liste? -> aus Operator +
    return *this;
}

List & List::operator + (const List & List_Append)
{
    // Die Methode +
    // Es werden zwei Listen aneinander gehangen.
    // Dabei werden beide Ursprungslisten nicht verändert. Es entsteht eine neue Ergebnisliste.
    Node * tmp_node;
    List * tmp;
    if (temp) {                                        // this ist eine temporäre Liste und kann verändert werden
        tmp = this;
    }
    else {
        tmp = new List(this);                        // this ist keine temporäre Liste -> Kopie erzeugen
        tmp->temp = true;                            // Merker setzten, dass es sich um eine temporäre Liste handelt
    }
    if (List_Append.list_size) {                    // anhängen der übergebenen Liste an tmp
        tmp_node = List_Append.head_tail->next;
        while (tmp_node != List_Append.head_tail) {
            tmp->insertBack(tmp_node->key);
            tmp_node = tmp_node->next;
        }
    }
    if (List_Append.temp) delete & List_Append;        // wurde eine temporäre Liste übergeben, dann wird diese gelöscht                       
    return *tmp;
}

List & List::operator + (const List * List_Append)
{
    // Die Methode +
    // Es werden zwei Listen aneinander gehangen.
    // Dabei werden beide Ursprungslisten nicht verändert. Es entsteht eine neue Ergebnisliste.
    Node * tmp_node;
    List * tmp;
    if (temp) {                                        // this ist eine temporäre Liste und kann verändert werden
        tmp = this;
    }
    else {
        tmp = new List(this);                        // this ist keine temporäre Liste -> Kopie erzeugen
        tmp->temp = true;                            // Merker setzten, dass es sich um eine temporäre Liste handelt
    }
    if (List_Append->list_size) {                    // anhängen der übergebenen Liste an tmp
        tmp_node = List_Append->head_tail->next;
        while (tmp_node != List_Append->head_tail) {
            tmp->insertBack(tmp_node->key);
            tmp_node = tmp_node->next;
        }
    }
    if (List_Append->temp) delete List_Append;        // wurde eine temporäre Liste übergeben, dann wird diese gelöscht                   
    return *tmp;
}

void List::format(const std::string & start, const std::string & zwischen, const std::string & ende)
{
    // Setzen des Formates für die Ausgabesteuerung der Liste bei cout
    // das Format wird für den überladenen Operator << verwendet
    list_form.start = start;
    list_form.zwischen = zwischen;
    list_form.ende = ende;
}

std::ostream & operator<<(std::ostream  & stream, List const & Liste)
{
    // Ausgabe der Liste mit cout
    stream << Liste.list_form.start;
    for (Node * tmp = Liste.head_tail->next; tmp != Liste.head_tail; tmp = tmp->next)
        stream << tmp->key << (tmp->next == Liste.head_tail ? Liste.list_form.ende : Liste.list_form.zwischen);
    if (Liste.temp) delete & Liste;            // wurde eine temporäre Liste übergeben, dann wird diese gelöscht
    return stream;
}

std::ostream & operator << (std::ostream & stream, List const * Liste)
{
    // Ausgabe der Liste mit cout
    stream << Liste->list_form.start;
    for (Node * tmp = Liste->head_tail->next; tmp != Liste->head_tail; tmp = tmp->next)
        stream << tmp->key << (tmp->next == Liste->head_tail ? Liste->list_form.ende : Liste->list_form.zwischen);
    if (Liste->temp) delete Liste;            // wurde eine temporäre Liste übergeben, dann wird diese gelöscht
    return stream;
}

Also das ist jetzt schon etwas aber es ging halt nur um diese ein paar Sachen, die wir machen sollten. Ich hab das jetzt so in der Art gemacht. Ist jetzt nicht das gesamte Projekt, nur halt die eine cpp-datei.
 
Gibt es jetzt auch eine konkrete Frage zu diesem Code?

Der Code ist absolut unlesbar. Außerdem, was ist das für komische Art von Liste? Eine leere Liste hat als nächstes und vorheriges Element sich selbst, warum?!
Wieso wächst die Liste in beide Richtungen, wenn man insertFront(int key) verwendet?
Was sollen die ganzen next->prev? Bei einer Liste sollte das vorherige Element des nächsten Elements einfach das aktuelle Element sein.

Ich blicke nicht durch. Das macht alles keinen Sinn.

Gruß
BlackMark
 
Also jetzt fragen habe ich dazu nicht mehr, den habe das erstmal gelöst. Das ganze habe ich selbst nicht entworfen. Für das Praktikum haben wir einen vorgeschrieben Code bekommen welches wir ergänzen sollen. das mit dem head_tail finde ich persönlich auch blöd aber wenn die Dozentin es so möchte habe ich ja keine Wahl. Ich hab noch weitere 4 cpp/header dateien. Bei
C++:
insertFront(int key)
wächst er in eine Richtung, da ist halt kein tail sondern ein head_tail also nur ein Knoten. Das
C++:
->next
ist ein Pointer welches auf das nächste Knoten zeigt und bei
C++:
->prev
zeigt es auf das vorherige knoten. Als komplettes Paket macht das nur sinn. Deswegen wollte ich nicht direkt alles posten für so eine Winzige frage. Danke aber für deine Hilfsbereitschaft.
 
Wie viel von dem Code wurde bereitgestellt? Denn das ist alles absolut schrecklicher Code. Sehr viel bad practice und verstößt so ziemlich gegen alle coding conventions.

Ich gehe mal auf ein paar Sachen ein die mir auffallen:
if (_List.temp) delete & _List; in einer Funktion mit der Signatur List::List(const List & _List). Der copy constructor darf nicht den Speicher des übergebenen Objekts löschen. Deswegen ist es ja const. Das bricht komplett die Annahme die man hat wenn man ein Objekt als const & übergibt. Gilt nicht nur für den copy constructor, kommt ja mehrmals in diesem Code vor.
Der gesamte Code hat unmengen an sinnloser Code duplication. Das könnte man vermutlich von 600 Zeilen auf 200 Zeile Code reduzieren.
Die Swap Funktion ist viel zu lang. Funktionen sollten kurz und übersichtlich gehalten werden. Komplexe Funktionen sollten mittels Hilfsfunktionen mit passenden Namen vereinfacht werden.
Eine Variable temp und eine andere Variable tmp zu haben hilft nicht bei der Lesbarkeit und führt sicherlich nur zu Fehlern. Variablen sollten sprechende Namen haben.

Wenn ihr solchen Code bekommt um etwas zu lernen tut mir das wirklich leid, denn hier kann man nur lernen wie man es auf gar keinen Fall machen soll. Ich verstehe immer noch nicht was für eine komische Art von Liste das überhaupt sein soll. Wenn ich raten müsste, würde ich sagen eine doppelt verkettete zirkuläre Liste. Wenn dem so ist, dann sollte die Klasse auch CircularLinkedList heißen und nicht einfach nur List.

Gruß
BlackMark
 
BlackMark schrieb:
Wieso wächst die Liste in beide Richtungen, wenn man insertFront(int key) verwendet?
Sie wächst ja schon nur um ein Element, aber es handelt sich ja um eine Ringliste. Also zeigt das letzte Element auch immer auf das erste und umgekehrt. Ich weiß ja nicht wie tief das Thema Listen beim TE schon behandelt worden ist, aber wenn das mehr oder weniger der Einstieg ist, finde ich es sehr fraglich hier mit einer doppelt verketteten Ringliste loszulegen.

Was sollen die ganzen next->prev? Bei einer Liste sollte das vorherige Element des nächsten Elements einfach das aktuelle Element sein
Das kenne ich aber auch so. Wenn ich hinter einem Element A ein neues Element X einfügen will muss ich ja von allen 3 betroffenen Elementen die Zeiger umbiegen und auf das ursprüngliche Folgeelement B kann ich ja nur über A->next zugreifen. Der Lesbarkeit wäre aber sicherlich geholfen, wenn man sich in diesem Fall A->next als lokale Variable merkt.
 
Also ich hab alle methoden zum einfügen, löschen und ausgeben z.b. getback und die swap Funktion hätte ich kürzer halten können. Den Deconstructor habe ich auch gemacht. Die Operator fkt. waren auch vorgegeben. Der Rest war auch vorgegeben.
 
Life Sucks schrieb:
Das Ding heißt Destructor.

C++:
List::List(const List & _List)
{
    /*
    ...
    */
    
    if (_List.temp) delete & _List;        // ist die Übergebene Liste eine temporäre Liste? -> aus Operator +
}
Dieses wundervolle Konstrukt stammt also nicht von dir? Dann merk dir gleich, dass man soetwas auf gar keinen Fall machen sollte. Auch wenn es C++ direkt nicht verbietet, ist das die Defintion von bad practice. Es ist schon nicht akzeptabel eine normale reference zu löschen (siehe Deleting a reference), aber in deinem Fall ist es noch dazu eine const reference, da erwartet man, dass sich das übergebene Objekt nicht verändert. Noch schlimmer ist, dass diese Member Funktion in C++ eine spezielle Bedeutung hat und einen copy constructor darstellt. Der copy constructor sollte gewisse Garantien geben, wie zB dass man damit ein Objekt kopieren kann, ohne das alte Objekt zu verändern. Wenn nach einem copy constructor Aufruf das alte Objekt auf einmal gelöscht wurde, dann macht das überhaupt keinen Sinn und niemand würde mit so einem Verhalten rechnen.

Gruß
BlackMark
 
  • Gefällt mir
Reaktionen: Life Sucks und new Account()
Vollzitate bitte künftig vermeiden. Danke! (Bitte die Forumregeln beachten!)
BlackMark schrieb:
Das Ding heißt Destructor.

C++:
List::List(const List & _List)
{
    /*
    ...
    */
   
    if (_List.temp) delete & _List;        // ist die Übergebene Liste eine temporäre Liste? -> aus Operator +
}
Dieses wundervolle Konstrukt stammt also nicht von dir? Dann merk dir gleich, dass man soetwas auf gar keinen Fall machen sollte. Auch wenn es C++ direkt nicht verbietet, ist das die Defintion von bad practice. Es ist schon nicht akzeptabel eine normale reference zu löschen (siehe Deleting a reference), aber in deinem Fall ist es noch dazu eine const reference, da erwartet man, dass sich das übergebene Objekt nicht verändert. Noch schlimmer ist, dass diese Member Funktion in C++ eine spezielle Bedeutung hat und einen copy constructor darstellt. Der copy constructor sollte gewisse Garantien geben, wie zB dass man damit ein Objekt kopieren kann, ohne das alte Objekt zu verändern. Wenn nach einem copy constructor Aufruf das alte Objekt auf einmal gelöscht wurde, dann macht das überhaupt keinen Sinn und niemand würde mit so einem Verhalten rechnen.

Gruß
BlackMark

Danke das werde ich mir merken
 
Zurück
Oben