简体   繁体   中英

allocated memory gets reclaimed

hi I'm tying to code my own list class actually it works like the std::vector class. The problem is when I use new to allocate memory for the next list, it Works fine. but when i try to allocate memory for the target(data) it gets reclaimed when the program reaches to the end of the scope of push_back() I dont understand why this two do not happen the same way and how can I use allocated memory for my data without it getting distroyed?

the code is here

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

in other words why it->next->target and/or it->target get destroyed when push_back returns?

正在销毁(或调用析构函数)的是在下一行作为输入参数创建的临时对象:

push_back(pos(first,second));

In

void list::push_back(const pos target)

target is being passed by value, so the target inside push_back is a temporary copy. When the function ends the copy will go out of scope and be destroyed. This is what you are seeing. Annoying, but not your real problem.

list violates the Rule of Three . This means when a list is copied it is not copied correctly. The pointers are copied and not the items pointed-at. Every time a list is copied, both the original and the copy point at the same places. When the copy goes out of scope and is destroyed, it takes the original's data with it.

It just so happens that you pass exclusively by value, so there is a lot of copying and destroying going on. The print function, for example, will incorrectly copy and then obliterate the provided list when it returns.

Solution: Add a copy constructor and an assignment operator to list that works its way through the list and copies all of the links and read up on pass by reference.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM