Reputation: 95
I'm developing a game and I have a tree class. The class has an int called "wood" which keeps the amount of wood left in the tree. There is also a function to keep track of all events. When the value reaches zero I want to delete this object.(By the way I'm using CodeBlocks and SDL library)
The handle_events functions:
void Tree::handle_events(SDL_Event event, int MouseX, int MouseY, int Xoffset, int Yoffset) {
if(event.type == SDL_MOUSEBUTTONDOWN) {
if( event.button.button == SDL_BUTTON_LEFT ) {
if((MouseX >= (xPos - Xoffset)) && (MouseX <= ((xPos + 50) - Xoffset)) && (MouseY >= (yPos - Yoffset)) && (MouseY <= ((yPos + 50) - Yoffset))) {
selected = true;
} else {
selected = false;
}
}
}
if(wood <= 0) {
delete this;
}
}
When I launch the game and "wood" gets to zero the tree is still there and working. Please help
EDIT:
while(SDL_PollEvent(&event)) {
MouseX = event.motion.x;
MouseY = event.motion.y;
menu_button.handle_button_events(event, MouseX, MouseY);
exit_button.handle_button_events(event, MouseX, MouseY);
for(int i = 0; i < trees.size(); i++)
{
trees[i].handle_events(event, MouseX, MouseY, Xoffset, Yoffset);
}
for(int i = 0; i < stones.size(); i++)
{
stones[i].handle_events(event, MouseX, MouseY, Xoffset, Yoffset);
}
for(int i = 0; i < bushes.size(); i++)
{
bushes[i].handle_events(event, MouseX, MouseY, Xoffset, Yoffset);
}
if(event.type == SDL_QUIT) {
running = false;
}
if(event.type == SDL_KEYDOWN) {
switch(event.key.keysym.sym) {
case SDLK_ESCAPE:
running = false;
}
}
if(exit_button.clicked) {
running = false;
}
if(menu_button.clicked) {
paused = true;
}
}
Trees is a vector containing all trees on the map
Upvotes: 0
Views: 1084
Reputation: 21778
What is trees
in trees[i]
? I presume it is std::vector<Tree*>
or similar?
When you call delete this
you are deleting the object referenced by trees[i]
, but you are not deleting the entry in the vector. After the deletion trees[i]
points to some freed up memory which - if not overwritten by something else - will still look like a tree object.
I would suggest doing something like this:
for(int i = trees.size()-1; i >= 0; i--) {
trees[i].handle_events(event, MouseX, MouseY, Xoffset, Yoffset);
if (trees[i].isEmpty()) {
delete trees[i];
trees.erase(trees.begin()+i);
}
}
Note, that iterating from the end is important, because when element is removed, all the follow-ups will be shifted.
If the vector is big and you do a lot of deletions, consider using a different structure which does not provide random access, since deletion from a vector can be time consuming.
Update:
I assume the member function Tree::isEmpty()
is implemented by you with the logic specifying when an object is empty and no longer needed, but without actually deleting the object.
Since, as you say, trees
is a vector of Tree
objects, and not pointers of thereof, you should never delete those objects yourself! The vector is the owner of those objects and it will delete them.
For that reason, you should just call trees.erase(trees.begin()+i)
and it will discard the object.
Upvotes: 2
Reputation: 5919
delete this
does not actually clean up pointers that still exist to the object. (It does call the destructor -- but since you have an empty destructor, no such cleanup gets done here, either.) After you delete this
, there will still be a (dangling!) pointer to the deleted Tree in the trees
vector.
One possible result of using this pointer is that the tree still appears, another possibility is a crash. There is no way to tell a dangling pointer from a valid pointer using just the pointer.
For this reason among others, delete this
is often a bad idea and never a simple solution.
You could consider checking whether a tree has run out of wood from the function that calls handle_events() -- then you can both delete the tree, and also remove the pointer from the vector.
Upvotes: 1