Re: Deleting Pointers from STL Vector
kanze_at_gabi-soft.fr
Date: 10/04/03
- Next message: yaron: "Re: MFC(month calendar)"
- Previous message: WW: "Re: std::pair<,>"
- In reply to: Hanzo: "Deleting Pointers from STL Vector"
- Next in thread: WW: "Re: Deleting Pointers from STL Vector"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: 3 Oct 2003 21:51:30 -0400
Hanzo <hanzo@milclan.com> wrote in message
news:<omhnnv4l0nfkbdv7014dovil94s2ang3g1@4ax.com>...
> I'm iterating over a vector of base class pointers and deleting those
> which meet a certain criteria...i'm using pretty text-book code for
> the particular delete/erasure (it's straight out of Myers' Effective
> STL), and reads like this:
> void CGame::RemoveDeadObjects()
> {
> // cleanup crew!!
> vector<CDrawableObject*>::iterator i;
>
> for (i = g_vecGameObjects.begin(); i != g_vecGameObjects.end();)
> {
> // if object is not null and can be removed...
> if ((*i) && (*i)->CanRemove())
> {
> // grab hold before erasure
> CDrawableObject* toDie = *i;
> // erase...
> i = g_vecGameObjects.erase(i);
> // ...and kill
> delete toDie;
> toDie = NULL;
> }
> else
> ++i;
> }
> }
> Here's the problem: on the two lines that say delete toDie; toDie =
> NULL; I am noticing that the original variable to which toDie is
> pointing is not being set to NULL, just "toDie" itself.
Normal, no. You told the compiler to set toDie to NULL. You didn't tell
it to do anything else. In this case, setting toDie to NULL is for all
intents and purposes a no-op, and a any halfway good optimizing compiler
will eliminate the line completely.
I'm not sure what you mean by "the original variable". The variable
toDie contains a copy of the element which was in the vector. This
element has been erased. It doesn't exist any more, so it can't be set
to NULL.
There may, of course, be other variables designating the element. The
compiler has no way of knowing this, and it is your responsibility to
manage them. There are several alternatives, according to your needs:
- If just setting them to null is sufficient, there are different
types of smart pointers. If you use boost::shared_ptr in the array,
any boost::weak_ptr pointing to the object will appear to be NULL;
in many cases, this is a sufficient solution. If for some reason,
using boost::shared_ptr is not an alternative (although frankly, I
cannot think of one), I have a ManagedPtr at my site which will
automatically become null when the pointed to object is destructed;
it is considerably less flexible than the Boost solution, however,
since it places significant constraints on the pointed to object.
- If you are storing the pointers in other collections, say because
another object might want to refer to several GameObjects, then you
also need some way of removing the pointers from the collection
entirely, to avoid memory leaks. The simplest way to do this is
just to use weak_ptr, as above, and scan the collection periodically
(say each time you modify it) to suppress any weak_ptr whose objects
no longer exist. If the collections are really large, however, this
may have unacceptable runtime overhead. In such cases, you need
some means of informing the collection; this implies some sort of
notification mechanism, in which the collection is a listener. My
ManagedPtr uses a notification to inform the pointers to be set to
null, and could easily be adopted to handle additional
notifications. While this is definitely overkill when the first
solution works, if you do need notification, the added complexity
that ManagedPtr introduces will be necessary anyway.
- More generally, it may be that the object holding a pointer to the
deleted object needs to do more than just delete the relationship.
In this case, you need to use the Observer pattern. The destructor
of the object informs all classes which have expressed an interest
in it that it is going to die, and they do whatever they have to do.
> In other words, if one of the CDrawableObjects* was say, a member var
> of CGame called m_cdPlayer1, when the delete/set-to-NULL happens:
> 1. Before the delete, toDie and m_cdPlayer1 have a value of
> 0x00a72498.
> 2. After the delete, both toDie and m_cdPlayer1 have their __vfptr
> point to memory 0xFEEEFEEE (signifying a delete)
I think you are speaking about something in the pointed to object
itself. If both pointers point to the same address, it is normal that
reading through either pointer will result in the same thing.
> 3. After the set-to-null, the value of toDie becomes 0x00000000, while
> m_cdPlayer1 remains at a value of 0x00a72498 (while still pointing to
> 0xFEEEFEEE).
What else should (or even could) happen. The compiler has no way of
knowing which objects might or might not have pointers to the same place
as toDie. Changing toDie changes toDie, and nothing else in the
program.
> Not the behavior I want. At this point, m_cdPlayer1 is officially
> deleted, yet the test "if (m_cdPlayer)" fails, since it is technically
> not NULL.
> Any suggestions or recommendations on how to get the intended behavior
> out of this snippet?
See above. The easiest solution to begin with is to use
boost::shared_ptr in the vector, and boost::weak_ptr every where else.
But sooner or later, you'll run into a case where you need full
notification; every professional I know of has some sort of change
notification mechanism in his toolbox.
-- James Kanze GABI Software mailto:kanze@gabi-soft.fr Conseils en informatique orientée objet/ http://www.gabi-soft.fr Beratung in objektorientierter Datenverarbeitung 11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16 [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
- Next message: yaron: "Re: MFC(month calendar)"
- Previous message: WW: "Re: std::pair<,>"
- In reply to: Hanzo: "Deleting Pointers from STL Vector"
- Next in thread: WW: "Re: Deleting Pointers from STL Vector"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|