It is because of the delete in the destructors of tree on the nut array which is uninitialized. Simply adding the initialization of nuts to a null array in the constructor fixes it:
1 2 3 4 5 6
|
Tree::Tree()
// the initialization of nuts to a null array
: nuts(0)
{
this->nuts_left = 20;
}
|
Because when the destructor of Tree is called, the
Isn't invalid because it knows it is an empty array. However, without initializing it, it will not know it is an empty array and then it tries to free some memory that was never allocated.
At first glance, you might think the Hoard class has the same issue but since, in main, Hoard is called with a
new
, the destructor for the allocated Hoard objects isn't ever called because you don't ever call
delete
on the Hoard objects. Since the Tree object is an automatic variable, that is, it has a scope (of the main function), when the main finishes, the Tree variable goes out of scope and the destructor is automatically called. Thus when the program completely finishes and cleans up the automatic variables at the end when exiting, it calls the destructor of Tree and you get a seg fault because the "nuts" of Tree were never initialized.
In other words, every
delete
should have a corresponding
new
and vice versa. New and delete have to do with pointers, which is something many people struggle to wrap their head around right off the bat. When new is called and you make a pointer to the memory location new allocated for your pointer/array, you are essentially removing the variable(s) pointed to by the pointer/array from having a scope and thus why you have to call delete on it when you are done with. In other words, when the program is running, the memory for that variable keeps the same location and value (if you aren't changing it obviously) no matter where you are in the code until deallocate (delete) it. Stepping over how pointers enable polymorphism, that is one of the great advantages of pointers: you can free variables from having a scope and pass them around and make copies of the pointer and change the value at the memory location wherever you want in the code and all the other copies of the pointer will see the effect because all a pointer does is identify a certain location in memory you put a variable and if you modify what is AT that location in memory all the other copies of the pointer "see" it. A C-style array is just a pointer to the start of the memory block where you allocated several memory slots of the size of the class, i.e. a C-style array of doubles of size 10 (
double* myarray = new double[10]
) is a pointer to a block of 80 bytes (each double is 8 bytes X 10 elements = 80 bytes).