C++ - how to delete sub-classes in destructor - c++

Here is a class definition:
class Person {
private:
char* name;
int numChildren;
Person** childrenList;
public:
Person(char* name);
~Person();
};
In the Person::Person() constructor, it will set up the name of the person based on the constructor parameter, and then create Person object for each child, and each child may have other children. And let's say for one case, after I run this: Person* me = new Person("Alex");, the following structure will be created:
ie if me is created, me's children will also be recursively created.
But I have a trouble in the Person::~Person() destructor. In the destructor it should delete all dynamic objects including name and every child. Here is my attempt:
Person::~Person() {
for (int i = 0; i < numChildren; i++) {
// go inside each child
}
delete[] this->name;
delete[] childrenList;
}
But I don't know how to go inside each child, and the destructor has no parameter.
Could anyone give me some hint? Thanks!

Just delete each child before you delete[] childrenlist :
Person::~Person()
{
for (int i = 0; i < numChildren; i++) {
delete childrenList[i];
}
delete[] childrenList;
...
}

when using a double poiner like Person** childrenList, you have to do this to allocate and delete it:
unsigned len1 = 100;
unsigned len2 = 100;
// childrenList is a pointer to a an array of pointers
Person** childrenList = nullptr;
// create an array with UNALLOCATED Person pointers, note the "*"
childrenList = new Person*[len1];
// allocate all the pointers in the the array
for (size_t i1 = 0; i1 < len1; i1++)
childrenList[i1] = new Person;
// delete all the pointer in the array
for (size_t i1 = 0; i1 < len1; i1++)
if (childrenList[i1])
delete childrenList[i1];
// delete the array itself
delete[] childrenList;
you could put this in your destructor:
Person::~Person()
{
// delete all the pointer in the array
for (size_t i1 = 0; i1 < len1; i1++)
if (childrenList[i1])
delete childrenList[i1];
// delete the list itself
delete[] childrenList;
}
But this whole thing would be done easier with a "2d" std::vector:
vec<vec<Person>> childrenList;
Such a 2d vector has its own syntax, but it is easier and less error prone than "bare" pointers/arrays.-
PS: I have NOT tried to compile or run this example.

Related

Issues with dynamic arrays, pointers and copy-constructors

I'm having a lot of issues with creating a dynamic array containing objects.
As I've understood it, because my array is handling objects, the class stored in the array must have a copy constructor or an assignment operator so that all will be copied properly.
I've successfully created this program with a normal array of defined size. Now I have a lot of problems creating the same program with a dynamic array.
Class 1 The objects to be stored:
class objToBeStored{
private:
string dataToBeStored;
int sizeOfArray;
string *storedArray;
public:
objToBeStored(); //empty constructor
objToBeStored& operator =(const objToBeStored& o); // assignment operator
~objToBeStored(); //destructor (no code inside);
bool getData(istream &stream);
//.....other methods to do stuff
};
objToBeStored::objToBeStored(){
//empty
}
objToBeStored& objToBeStored::operator=(const objToBeStored& o){
if(this != o){
dataToBeStored = o.dataToBeStored;
for (int i = 0; i < sizeOfArray; i++){
storedArray[i] = o.storedArray[i];
}
}
return *this;
}
void objToBeStored::getData(istream &stream){
stream >> dataToBeStored >> sizeOfArray;
storedArray = new string[sizeOfArray];
for(int i = 0; i < sizeOfArray; i++){
stream >> storedArray[i];
}
return !stream.eof();
}
//.....other methods to do stuff
Class 2 contains the dynamic array that stores the above objects. Everything is working,except how I declared my dynamic array and the functions handling it. Therefore I will write this code below:
class storageArrayClass{
private:
storageArrayClass *store;
storageArrayClass *storptr;
int numberOfstored;
public:
storageArrayClass(); //empty constructor
~storageArrayClass();
void addElm(objToBeStored & o);
//other functions to do stuff
};
storageArrayClass::storageArrayClass(){ //constructor
numberOfstored = 0;
}
storageArrayClass::~storageArrayClass(){
}
void storageArrayClass(istream &stream) {
objToBeStored o;
o.getData(stream);
if(numberOfstored == 0){ //check it this is the first element
store = new objToBeStored[1]; //create a new array with length 1
store[(numberOfstored] = o; //store object
}else{
objToBeStored tmpStore = new objToBeStored[(numberOfstored+1]; //create a temp. array with 1 more position
for(int i=0; i < numberOfstored; i++){
tmpStore[i] = store[i]; //copy original array to the temp. array
storptr = &tmpStore[i]; // increment a point
}
storptr++; //increment pointer to last position
*storptr = o; //store object in last position
delete[] store; //delete the original array
store = new objToBeStored[(numberOfstored+1]; //create a new original array
store = tmpStore;//copy temp. array
}
}
I manage to add 3 objects to my dynamic array before I get the following error:
Process returned -1073741819 (0xC0000005) execution time : 5.059 s
Please help. I've read countless threads here, but I cannot get it to work.

C++ destructor throws error

I have the following code:
class MyList
{
private:
public:
int* list;
int size = 0;
int max;
// constructor
MyList(int s)
{
max = s;
size = 0;
if(max > 0)
list = new int[max];
};
// destructor
~MyList()
{
for (int x = 0; x < max; x++)
delete (list + x);
};
};
I tried to clear the memory with that destructor. However, it throws an error on second iteration. What did I do wrong? Also, it wouldn't let me do it this way:
delete list[x];
Can someone explain to me why? Thank you so much.
You should use delete[] because list is created via new[]-expression. e.g.
// destructor
~MyList()
{
delete[] list;
}
Note that they must be pair; new int[max] create an array containing max's elements, delete[] destroy the whole array. delete should only be used for pointer created by new.
And better to change the constructor to
// constructor
MyList(int s)
{
max = s;
size = 0;
if(max > 0)
list = new int[max];
else
list = nullptr;
}
to make sure list is always valid.
Try this:
MyList(int s)
: max(s),
size(0),
list(new int[s])
{
};
~MyList()
{
delete[] list;
};
i dnt understand why are you using
a loop to deallocate that memory.... you should simpy write
delete[] list;
that would be enough!
in your destructor you are using delete (list(a pointer)+x) this is not deallocating memory you created...
you are tryin to delete addresses next to your list by adding value of x loop in it
i hope you understood your error :)

Memory leaks from 2d array on heap

I'm having an issue with a lot of memory leaks from a class I've created. The assignment is requires creating a word search puzzle on the heap. I've created my destructor, copy constructor and overload the assignment operator.
I think there must be something wrong with one of these functions, because the final check to ensure it is working is to create objects in a loop, to see if it fails and my function is crashing. I've tried different forms of the destructor and I've tried changing around the copy and assignment operator with no luck. Kind of at a loss, and the lack of warnings is really making it difficult to debug without a proper understanding of the heap.
Any help would be really appreciated!
Here are some functions that are working with the heap.
JumblePuzzle::~JumblePuzzle(){
for (int i = 0; i < size; ++i){
delete jumble[i];
}
delete jumble;
}
JumblePuzzle::JumblePuzzle(string word, string diff){
int i = 0;
toHide = word;
difficulty = diff;
jumble = buildArray();
fillArray();
hideWord();
}
JumblePuzzle::JumblePuzzle(JumblePuzzle& temp){
size = temp.size;
rowPos = temp.rowPos;
colPos = temp.colPos;
direction = temp.direction;
toHide = temp.toHide;
difficulty = temp.difficulty;
jumble = temp.getJumble();
}
JumblePuzzle& JumblePuzzle::operator=(const JumblePuzzle& right){
if (this != &right){
for (int i = 0; i < size; ++i){
delete jumble[i];
}
delete[] jumble;
size = right.size;
rowPos = right.rowPos;
colPos = right.colPos;
direction = right.direction;
toHide = right.toHide;
difficulty = right.difficulty;
jumble = right.getJumble();
}
return *this;
}
charArrayPtr* JumblePuzzle::buildArray() const{
charArrayPtr* array = new char*[size];
for (int i = 0; i < size; ++i){
array[i] = new char[size];
}
return array;
}
Here's the line its failing on.
int loopLimit =20;
for (int i = 0; i < loopLimit; i++)
JumblePuzzle jp("HIDDENWORD", "hard");
Thanks for any possible help!
EDIT:
Here is my .h file as well.
#ifndef JUMBLE_H_
#define JUMBLE_H_
#include <time.h>
#include <cstdlib>
#include <string>
using namespace std;
typedef char* charArrayPtr;
class BadJumbleException {
public:
BadJumbleException(const string&);
string& what();
private:
string message;
};
class JumblePuzzle{
public:
JumblePuzzle(string, string); //simple constructor
JumblePuzzle(JumblePuzzle&); //copy constructor
~JumblePuzzle(); //deconstructor
charArrayPtr* getJumble() const;
JumblePuzzle& operator=(const JumblePuzzle&);
//accessors
int getSize();
int getRowPos();
int getColPos();
char getDirection();
private:
//attributes
int size;
int rowPos;
int colPos;
char direction;
charArrayPtr* jumble;
string toHide;
string difficulty;
void fillArray();
void hideWord();
char randomDirection();
int randomNum(int);
charArrayPtr* buildArray() const;
};
#endif
and my getJumble. It's used to get the actual word search created. Returned a copy rather than the pointer so it cant be modified.
charArrayPtr* JumblePuzzle::getJumble() const{
charArrayPtr* tempJumble = new char*[size];
for (int i = 0; i < size; ++i){
tempJumble[i] = new char[size];
}
for (int i = 0; i < size; i++){
for (int j = 0; j < size; j++){
tempJumble[i][j] = jumble[i][j];
}
}
return tempJumble;
}
There is one major thing wrong with your code, and that is you failed to initialize the "size" member in the JumblePuzzle(string, string) constructor.
There are other things you should do:
1) Create a separate function to destroy the 2d array within the JumblePuzzle class. You seem to be copying the same loops to do this in multiple places. No need for that if you just call a function to do this work.
2) Your assignment and copy constructor are not exception safe. If new[] throws an exception during the creation of the copy, then the original object has invalidated data. In other words, you've destroyed the data, and when you want to create another 2d array, when new[] says "oops", you've destroyed your original data and can't get it back.

Memory leak when resizing dynamic array

Here's my code:
template<class T> class Test
{
public:
int Size = 0;
int Length = 0;
T* Items;
Test() {}
~Test()
{
delete [] Items;
}
void Append(const T& newItem)
{
if (Size + 1 >= Length)
{
Length += 250;
T* old = Items;
Items = new T[Length + 250];
for (int i = 0; i < Size; i++)
Items[i] = old[i];
delete [] old;
}
Items[Size] = newItem;
Size++;
}
};
Test<int> test;
for (int i = 0; i < 500000; i++)
test.Append(i);
I'm populating the dynamic array with 500000 integers which must take just 1-2Mb but it takes about 30Mb. There's no problem if i set the initial size to 500000(i.e. no resizing occurring). The grow value(250) seems to affect the memory somehow, if it's larger(for example 1000) then the memory usage is pretty low. What's wrong?
Typically, when you are reallocating an array, you do not want to modify the actual array until the very last second (to maintain exception safety):
T* temp = new T[new_size];
// assume count is the previous size and count < new_size
std::copy(Items, Items + count, temp);
std::swap(temp, Items);
delete [] temp;
Aside from that, there is nothing visible in your code that would cause a memory leak.
The extra size can possibly be due to other optimizations (being turned off) and/or debugging symbols being turned on. What compiler options are you using (and what compiler)? It should be noted that extra size is not necessarily an indication of a memory leak. Have you run this in a debugger or memory profiler which found a leak?
It should also be noted that std::vector does all of this for you.
Looking at your code, you're going to segfault more so than leak memory due to the fact that calling delete or delete[] on a non-NULL, but previously deallocated, pointer is a Bad Thing. Also, I don't believe this is your real code, because what you posted won't compile.
When you delete a pointer, always set it to NULL afterwards. It's good practice to initialize to NULL as well. Let's fix up your code to make sure we don't call delete on previously deallocated pointers. Also, let's initialize our pointer to NULL.
Your misuse of memory probably stems from the following lines of code:
Length += 250;
T* old = Items;
Items = new T[Length + 250];
Notice that you increment Length by 250, but then allocate Length+250 more elements? Let's fix that, too.
template<class T>
class Test
{
public:
int Size;
int Length;
T* Items;
Test() : Size(0), Length(0), Items(NULL){}
~Test() {
if (Items != NULL)
delete [] Items;
}
void Append(const T& newItem)
{
if (Size + 1 >= Length)
{
Length += 250;
T* old = Items;
Items = new T[Length];
for (int i = 0; i < Size; i++)
Items[i] = old[i];
delete [] old;
old = NULL;
}
Items[Size] = newItem;
Size++;
}
};
int main(){
Test<int> test;
for (int i = 0; i < 500000; i++)
test.Append(i);
}

When to delete class pointer from array

I have a list of pointer object *lst[200];
I use this to add one to it:
object a = new object();
a->id = current_amount;
lst[current_amount] = a;
current_amount++;
now I want to add a function delete it:
I simply want to remove this element from array: (I store an id use it to delete it)
void delete(object *elem)
{
if(!elem)
return;
for (int i = elem->id ; i < current_amount - 1;i++)
{
lst[i] = lst[i + 1];
}
}
Question: When to call delete elem? The code above doesn't free the memory at all...
void deleteElem(object *elem) // you can't call your function 'delete'
{
if(!elem)
return;
for (int i = elem->id ; i < current_amount - 1;i++)
{
lst[i] = lst[i + 1];
}
delete elem; // this free's the memory
}
Since the code above isn't C++, here's some that is:
std::list<std::unique_ptr<object>> lst;
and the methods erase, push_back, push_front.