2017-01-22 5 views
1

привет, я привязываю код к собственному классу списка, на самом деле он работает как класс std :: vector. Проблема заключается в том, что я использую new для выделения памяти для следующего списка, работает нормально. но когда я пытаюсь выделить память для цели (данных), она получает исправление, когда программа достигает конца области push_back() Я не понимаю, почему эти два не происходят одинаково и как я могу использовать выделенную память для моих данных без его разрушения?выделенная память получает исправление

код здесь

#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; 
} 

другими словами, почему it-> next-> мишени и/или it-> цель разрушаться, когда возвращается push_back?

+1

В качестве примечания стороны, * оба * 'new' и' malloc' * выделяют память для данных *. Вы должны перефразировать свой вопрос. И если возможно, отправьте сообщение [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

Ваш код не может быть [Правило трех] (http://en.cppreference.com/w/cpp/language/rule_of_three) совместимым. Пример: посмотрите, как 'print' принимает значение' list' по-умолчанию, что означает, что передача параметра использует копию экземпляра по умолчанию для экземпляра ctor, что означает, что теперь у вас есть два объекта 'list' с членами, указывающими на * тот же * динамический контент , Поскольку существует 'print', скопированный параметр уничтожается, в результате чего исходный законный владелец данных шляпы возвращается в' main() 'со стеком оборванных указателей. – WhozCraig

+0

, так что я должен сделать, чтобы сохранить исходный список в безопасности? – user3073850

ответ

2

В

void list::push_back(const pos target) 

target в настоящее время передается по значению, так target внутри push_back - временная копия. Когда функция закончится, копия выйдет из области действия и будет уничтожена. Это то, что вы видите. Раздражающе, но не твоя настоящая проблема.

list нарушает Rule of Three. Это означает, что при копировании list оно не скопировано правильно. Указатели копируются, а не пункты, на которые указывает. Каждый раз, когда копируется list, как оригинал, так и копия в тех же местах. Когда копия выходит из области действия и уничтожается, она берет с собой данные оригинала.

Как раз так бывает, что вы проходите исключительно по стоимости, поэтому происходит много копирования и уничтожения. Например, функция print будет неправильно копировать и затем стирать предоставленный list, когда он вернется.

Решение: добавьте конструктор копирования и оператор присваивания в list, который прокладывает себе путь по списку и копирует все ссылки и считывает их по ссылке.

2

То, что уничтожают (или деструктор вызывается) является временным, что создается в качестве входного параметра на следующей строке:

push_back(pos(first,second));