首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >分配的内存被回收

分配的内存被回收
EN

Stack Overflow用户
提问于 2017-01-22 11:24:12
回答 2查看 60关注 0票数 1

嗨,我正在编写我自己的list类,实际上它的工作方式类似于std::vector类。问题是,当我使用new为下一个列表分配内存时,它工作得很好。但是,当我尝试为目标(数据)分配内存时,当程序到达push_back()作用域的末尾时,它会被回收。我不明白为什么这两种情况不是以相同的方式发生的,我如何才能在不破坏数据的情况下为数据使用分配的内存?

代码在这里

代码语言:javascript
复制
#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;
}

换句话说,为什么当push_back返回时,它->下一个->目标和/或它->目标会被销毁?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-01-22 12:43:48

在……里面

代码语言:javascript
复制
void list::push_back(const pos target)

target是通过值传递的,因此push_back中的target是一个临时副本。当函数结束时,副本将超出作用域并被销毁。这就是你所看到的。很烦人,但不是你真正的问题。

list违反了Rule of Three。这意味着当list被复制时,它不会被正确复制。指针被复制,而不是指向的项。每次复制list时,原始点和复制点都位于相同的位置。当副本超出作用域并被销毁时,它会随身携带原始数据。

碰巧你完全是通过值传递的,所以有很多复制和销毁操作。例如,print函数将错误地复制所提供的list,然后在返回时将其清除。

解决方案:向list添加一个复制构造函数和一个赋值运算符,它会遍历列表并复制所有链接,然后按引用传递。

票数 2
EN

Stack Overflow用户

发布于 2017-01-22 12:21:11

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

代码语言:javascript
复制
push_back(pos(first,second));
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41786997

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档