2017-01-22 1 views
1

Hallo ich bin zu Code meine eigene Liste Klasse tatsächlich funktioniert es funktioniert wie die Klasse std :: vector. Das Problem ist, wenn ich new verwende, Speicher für die nächste Liste zu reservieren, es funktioniert gut. aber wenn ich versuche, Speicher für das Ziel (Daten) zu reservieren, wird es zurückgefordert, wenn das Programm bis zum Ende des Bereichs von push_back() erreicht Ich verstehe nicht, warum diese beiden nicht auf die gleiche Weise passieren und wie kann ich zugewiesenen Speicher verwenden für meine Daten ohne es zu zerstören?zugeordneter Speicher wird zurückbeordert

der Code ist hier

#include <iostream> 
#include <cstdlib> 

using namespace std; 

struct pos{ 
    int x; 
    int y; 

    pos() 
    { 
     x = y = 0; 
    } 

    pos(int x, int y) 
    { 
     this->x = x; 
     this->y = y; 
    } 

    pos& operator=(pos rhs) 
    { 
     x = rhs.x; 
     y = rhs.y; 
     return *this; 
    } 

    bool operator==(const pos& rhs) 
    { 
     if(x == rhs.x && y == rhs.y) 
      return true; 
     else 
      return false; 
    } 
    ~pos() 
    { 
     cout << "x =" << x << ", y =" << y << "got distorted!" << endl; 
    } 
}; 


class list { 
    private: 
     pos *target; 
     list* next; 
     int index; 
    public : 
     list(); 
     list(pos target); 
     void push_back (int first , int second); 
     void push_back (const pos target); 
     pos pop_back(); 
     pos* search(int first , int second); 
     pos* search(pos target); 
     int erase(int index); 
     pos get(int index); 
     void change(const pos target,int index); 
     void change(int first,int second,int index); 
     ~list(); 
}; 

void print(list lst); 
// function declarations 

list::~list() 
{ 
    cout << "list is destroyed!" << endl; 
    if(target != NULL) 
     delete target; 
    if(next != NULL) 
     delete next; 
} 

list::list() 
{ 
    target = NULL; 
    next = NULL; 
    index = 0; 
} 
list::list(pos target) 
{ 
    this->target = new pos(target); 
    index = 0; 
    next = NULL; 
} 

void list::push_back(const pos target) 
{ 
    cout << "push_back() begin" << endl; 
    list* it = this; 
    while(it->next != NULL) 
    { 
     it = it->next; 
    } 
    if(it->target == NULL) 
    { 
     it->target = new pos(target); 
    } 
    else 
    { 
     it->next = new list; 
     it->next->index = it->index+1; 
     //option one 
     it->next->target = new pos(target); 
     //option two 
     it->next->target = (pos*)malloc(sizeof(pos)); 
     (*it->next->target) = target; 
     //it->next->next is already NULL 
    } 
    cout << "push_back() end" << endl; 
} 

void list::push_back(int first , int second) 
{ 
    push_back(pos(first,second)); 
} 

pos list::pop_back() 
{ 
    print(*this); 
    list* it = this; 
    cout << "address of x is" << this << endl; 
    cout << "this->target is" << this->target << endl; 
    cout << (*target).x << endl; 



    if(it->target == NULL) 
     return *(new pos); // an error is occurred there is not any data to return! must find another solution maybe throw an exception 

    if(it->next == NULL) 
    { 
     pos return_data = *(it->target); 
     delete it->target; 
     it->target = NULL; 
     return return_data; 
    } 

    while(it->next->next != NULL) 
    { 
     cout << "it->target is" << it->target << endl; 
     it = it->next; 
    } 
    pos return_data = *(it->next->target); 

    delete it->next; 
    it->next = NULL; 

    return return_data; 
} 

pos* list::search(pos target) 
{ 
    list* it = this; 
    do 
    { 
     if(target == *(it->target)) 
      return it->target; 
     if(it->next != NULL) 
      it = it->next; 
     else 
      return NULL; 
    }while(1); 
} 
pos* list::search(int first , int second){ 
    return search(pos(first,second)); 
} 

int list::erase(int index){ 
    if(index < 0) 
     return 0; 


    list *it = this , *it_next = this->next; 
    if(index == 0) 
    { 
     if(it->next == NULL) 
     { 
      delete it->target; 
      return 1; 
     } 
     while(it_next->next != NULL) 
     { 
      it->target = it_next->target; 
      it = it_next; 
      it_next = it_next->next; 
     }//needs to be completed 

    } 


    do 
    { 
     if(it_next->index == index) 
     { 
      it->next = it_next->next; 
      delete it_next; 
      return 1; 
     } 
     if(it_next->next != NULL) 
     { 
      it = it_next; 
      it_next = it_next->next; 
     } 
     else 
      return 0; 

    }while(1); 


    return 1; 
} 

pos list::get(int index) 
{ 
    if(index < 0) 
     return *(new pos);//error 
    list* it = this; 
    do 
    { 
     if(it->index == index) 
     { 
      return *(it->target); 
     } 
     if(it->next != NULL) 
      it = it->next; 
     else 
      return *(new pos);//error , index is bigger than [list size] - 1 

    }while(1); 
} 

void list::change(const pos target,int index) 
{ 
    if(index < 0) 
     return ;//error 
    list* it = this; 
    do 
    { 
     if(it->index == index) 
     { 
      *(it->target) = target; 
     } 
     if(it->next != NULL) 
      it = it->next; 
     else 
      return;//error , index is bigger than [list size] - 1 

    }while(1); 
} 
void list::change(const int first,const int second,int index) 
{ 
    change(pos(first,second),index); 
} 

void print(list lst) 
{ 
    int idx = 0; 
    while(!(lst.get(idx)==pos(0,0))) 
    { 
     cout << "index " << idx << " : x = " << lst.get(idx).x << ", y = " << lst.get(idx).y << endl; 
     idx++; 
    } 
} 


int main(int argc, char const *argv[]) 
{ 
    list x; 
    cout << "address of x is" << &x << endl; 
    x.push_back(1,1); 
    x.push_back(2,2); 
    x.push_back(3,3); 
    x.push_back(4,4); 
    x.push_back(5,5); 
    print(x); 
    cout << "--------------------------" << endl; 
    x.pop_back(); 
    print(x); 
    cout << "--------------------------" << endl; 
    cout << x.get(2).x << endl; 
    x.erase(2); 
    print(x); 
    cout << "--------------------------" << endl; 
    return 0; 
} 

mit anderen Worten, warum it-> Weiter-> Ziel und/oder it-> Ziel erhalten, wenn push_back kehrt zerstört?

+1

Als eine Randnotiz, * sowohl * 'new' und' malloc' * Speicher für Daten * zuweisen. Sie müssen Ihre Frage neu formulieren. Und wenn möglich, poste ein [MCVE] (https://www.google.com.lb/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=0ahUKEwj7lIWr79TRAhUlK8AKHccxB_IQFggbMAA&url=http%3A%2F% 2Fstackoverflow.com% 2Fhelp% 2Fmcve & usg = AFQjCNEkKReghNZHBJSaky_hwPskMmG0ww). –

+2

Ihr Code ist nicht kompatibel mit [Rule of Three] (http://en.cppreference.com/w/cpp/language/rule_of_three). Beispiel: schau dir an, wie 'print' eine' liste' nach Wert nimmt, was bedeutet, dass der Parameter die standardmemberkopierende Kopie ctor verwendet, was bedeutet, dass du nun zwei 'list' Objekte hast, deren Mitglieder auf den * gleichen * dynamischen Inhalt zeigen . Wenn "print" existiert, wird der kopierte Parameter zerstört, wobei der ursprüngliche rechtmäßige Besitzer von hat-Daten mit einem Stapel von ungeeigneten Zeigern zurück in 'main()' gelassen wird. – WhozCraig

+0

Also was sollte ich tun, um die ursprüngliche Liste sicher zu halten? – user3073850

Antwort

2

In

void list::push_back(const pos target) 

target wird durch Wert übergeben wird, so Die target innerhalb push_back ist eine temporäre Kopie. Wenn die Funktion endet, wird die Kopie den Gültigkeitsbereich verlassen und zerstört werden. Das siehst du. Ärgerlich, aber nicht dein wirkliches Problem.

list verletzt die Rule of Three. Das bedeutet, wenn eine list kopiert wird, wird sie nicht korrekt kopiert. Die Zeiger werden kopiert und nicht die Elemente, auf die gezeigt wird. Jedes Mal, wenn eine list kopiert wird, zeigen sowohl das Original als auch die Kopie an den gleichen Stellen. Wenn die Kopie den Gültigkeitsbereich verlässt und zerstört wird, werden die Daten des Originals mitgenommen.

Es kommt einfach vor, dass Sie ausschließlich nach Wert übergeben, so dass es viel kopieren und zerstören geht. Die Funktion print zum Beispiel wird das bereitgestellte list fälschlicherweise kopieren und dann löschen, wenn es zurückkehrt.

Lösung: Fügen Sie einen Kopierkonstruktor und einen Zuweisungsoperator zu list hinzu, der sich durch die Liste arbeitet und alle Verknüpfungen kopiert und auf Verweis als Verweis weiterliest.

2

Was destroy wird (oder destructor genannt wird) die vorübergehende ist, dass in der folgenden Zeile als Eingabeparameter erstellt:

push_back(pos(first,second)); 
Verwandte Themen