2017-01-22 6 views
1

私は自分自身のリストクラスをコード化しようとしています。実際にはstd :: vectorクラスのように動作します。問題は、私がnewを使用して次のリストのメモリを割り当てるときです。 うまく動作します。しかし、私はターゲット(データ)のメモリを割り当てようとすると、プログラムがpush_back()のスコープの終わりに達すると再利用されます なぜこの2つが同じ方法で起こらないのか、どうして割り付けられたメモリ私のデータのためにそれはdistoされていない?割り当てられたメモリが回収される

コードは、ここでは、他の言葉で

#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->ネクスト>ターゲットおよび/またはIT->はターゲットが一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

あなたのコードは[Rule of Three](http://en.cppreference.com/w/cpp/language/rule_of_three)に準拠していません。例: 'print'が値で' list'を取る方法を見てください。つまり、パラメータを渡すとデフォルトのメンバーコピー用コピーctorが使用されます。つまり、メンバーが同じ*動的コンテンツを指し示す2つの 'list'オブジェクト。 'print'が存在するので、コピーされたパラメータは破壊され、帽子データの元の正当な所有者は、ダングリングポインタのスタックを持つ' main() 'に戻ります。 – WhozCraig

+0

元のリストを安全に保つために何をすべきですか? – user3073850

答えて

2

は値渡しされているので、 の中にはpush_backが一時的なコピーです。関数が終了すると、コピーは範囲外になり破棄されます。これはあなたが見ているものです。迷惑だが、本当の問題はない。

listは、Rule of Threeに違反しています。つまり、listがコピーされると、正しくコピーされません。ポインターはコピーされ、項目は指し示されません。 listがコピーされるたびに、元とコピーの両方が同じ場所を指します。コピーが範囲外になり破棄されると、元のデータがコピーされます。

あなたは値によって排他的に渡されるので、多くのコピーと破棄が行われます。たとえば、print関数は、返されたときに提供されたlistを間違ってコピーして消滅させます。

解決方法:コピーコンストラクタと代入演算子をlistに追加し、リスト内のすべてのリンクをコピーし、参照渡し時に読み取ります。

2

は次の行に入力パラメータとして作成した一時的なものである:

void list::push_back(const pos target) 

target

push_back(pos(first,second)); 
関連する問題