Sign in to follow this  
lodoss118

Erasing from a vector of pointers?

Recommended Posts

This is a two part question. I have created to classes image and sprite the image class has a list of images that is loaded separately from the sprite object so i can refer to same image without wasting memory space. i have implemented a refcount in the image class, so in theory i will never delete the image object unless its refcount is 0. in the sprite constructor i increment the image ref count. for now i am just deleting the image object in the sprite destructor. basic blueprint of each constructor image(path); ~image() { delete all images; } sprite(id, image); ~sprite() { delete image object; delete all sprites; } Now in my startup class which is where i load these objects Image *ryoStance = null; Sprite *test = null; OnLoad() { ryoStance = new Image(""); test = new Sprite(1, ryoStance); } OnUpdate() { if(test)test->Draw(); if(press a) { delete test; test = null; } Wprintf("RYO STANCE MEM LOC", ryoStance) } Now the problem is why does the ryoStance still have a memory location in my sprite destructor i delete this object and set it to null? In future when creating the sprite i will add the image reference to a manager that deals with the deletion of the images. ImageManager { static bool DeleteImages(Image *a) { if(a && a->refCount <= 0) { delete a; a = null; return true; } return false; } CleanImages() //will this work ok? { vector<Image *>::iterator last; last = removeIf(imageList.begin(), imageList.end(), DeleteImages); imageList.erase(last); } }

Share this post


Link to post
Share on other sites
Looking at it quickly, it looks OK in principle to me


You could create a more idiomatic functor, with an overloaded function call operator, and use the standard remove_if function.
Setting a to null is unnecessary as you're only affecting the local copy of the variable... Did you want to pass the pointer by reference instead?
Having a negative reference count should probably be flagged as an error.

Consider using one of Boost's smart pointer classes to do reference counting for you.

Share this post


Link to post
Share on other sites
yes i wanted to pass the pointer by reference.


but if ryoStance was created in main and the sprite destructor deletes it why does it still have a memory location? For now i haven't implemented the image manager as the sprite destructor has a pointer to image reference i delete this in its destructor which should delete ryoStance or where ever it is used?


Image *ryoStance = null;
Sprite *test = null;

OnLoad()
{
ryoStance = new Image("");
test = new Sprite(1, ryoStance);
}

OnUpdate()
{
if(test)test->Draw();

if(press a)
{
delete test; test = null;
}

Wprintf("RYO STANCE MEM LOC", ryoStance)
}

Share this post


Link to post
Share on other sites
I suppose test stores a copy of the pointer ryoStance. Setting one pointer to null doesn't affect other pointers that might also be pointing to the same resource. This is really why you'd use shared_ptr (it is perfectly possible to write code such that you don't need a single delete in your code).

Share this post


Link to post
Share on other sites
Pointers are analogous to street addresses.
Data is analogous to houses.
Code is like a blind monkey.

When you pass a pointer, you pass the street address.

When you call delete on a pointer, you order the demolition crew to destroy the house at that address. When you set a pointer to NULL, you simply throw away your copy of the street address.

So if you have a container of street addresses, and throw them away, the house remains.

If you have a container of street addresses, and you destroy the houses then throw away the addresses -- somewhere else in the code you can still have the street address.

You can tell your code (the blind monkey) to go to that address, open the door, and have a bath.

If it happens that the house has been destroyed, the blind monkey is likely to fall into a pit and break its neck on the way to the bath.

What is worse is that the neighbourhood is crowded. When you destroy a house, the wrecking crew automatically puts the deed up for sale. And the next house that is built (if it fits on the lot) can be built there. (Ie, when someone calls new, it can be put into the space you called delete on).

The new house can be anything, and have a completely different layout. And when your monkey tries to go to the bath, he'll smash through a glass window, drill a hole through your gas oven, take a piss on your bed on the way, and then lie down in your drawers. Because the new house isn't layed out like the old house, and the monkey is really clueless.

...

boost::shared_ptr<T> is an deed that is registered with the city commissioner of housing. Everyone who has this address has a 'right to enter' the house. So long as any of these rights exist, the house is left alone.

If the last right is lost, then the house is automatically put up for destruction. Abandoned houses are bad for real estate prices.

boost::weak_ptr<T> is an address that is registered weakly with the city commissioner of housing. From it, you can request a real registered address. If at any time all real registered addresses go away, the commissioner stops handing out real registered addresses to people with weak_ptrs.

You have to be careful not to leave a shared_ptr deed to house A in house B, and a shared_ptr deed to house B in house A. In that case, even if ever bit of active code loses the shared_ptr<T>, the city commissioner thinks that the houses are still in use. And doesn't send the wrecking crew over. This is known as a circular reference problem. weak_ptr<T> happens to be good for this: if you can break the cycle with it, the problem goes away.

You also have to be careful not to 'lose track of' shared_ptr<T>s. And finally, mixing shared_ptr<T> based code with code that stores normal T*s ... is bad.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this