Reputation: 109
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?
Upvotes: 1
Views: 63
Reputation: 33952
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.
Upvotes: 2
Reputation: 73
What is being destroy (or destructor being called) is the temporary that created as input parameter on the following line:
push_back(pos(first,second));
Upvotes: 2