Deleting Pointers from STL Vector

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Hanzo

    Deleting Pointers from STL Vector

    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::RemoveDe adObjects()
    {
    // cleanup crew!!
    vector<CDrawabl eObject*>::iter ator i;

    for (i = g_vecGameObject s.begin(); i !=
    g_vecGameObject s.end();)
    {
    // if object is not null and can be removed...
    if ((*i) && (*i)->CanRemove())
    {
    // grab hold before erasure
    CDrawableObject * toDie = *i;

    // erase...
    i = g_vecGameObject s.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.

    In other words, if one of the CDrawableObject s* 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)

    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).

    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?

    - Hanzo

    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.m oderated. First time posters: Do this! ]
  • Kevin Goodsell

    #2
    Re: Deleting Pointers from STL Vector

    [Cross-post to moderated group removed. I'd rather not wait for
    moderation. Generally, you should not cross-post to moderated groups.]

    Hanzo wrote:
    [color=blue]
    > 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::RemoveDe adObjects()
    > {
    > // cleanup crew!!
    > vector<CDrawabl eObject*>::iter ator i;
    >
    > for (i = g_vecGameObject s.begin(); i !=
    > g_vecGameObject s.end();)
    > {
    > // if object is not null and can be removed...
    > if ((*i) && (*i)->CanRemove())
    > {
    > // grab hold before erasure
    > CDrawableObject * toDie = *i;
    >
    > // erase...
    > i = g_vecGameObject s.erase(i);
    >
    > // ...and kill
    > delete toDie;
    > toDie = NULL;[/color]

    Why bother setting this to NULL when it's about to go out of scope and
    cease to exist?

    Also, there would be nothing wrong with doing this instead:

    delete *i;
    i = g_vecGameObject s.erase(i);
    [color=blue]
    > }
    > 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.[/color]

    The original variable to which toDie was pointing is gone. It doesn't
    exist. You deleted it. Once you've done that, you have no business
    attempting to determine its value.
    [color=blue]
    >
    > In other words, if one of the CDrawableObject s* was say, a member var
    > of CGame called m_cdPlayer1, when the delete/set-to-NULL happens:[/color]

    You are saying you have two different, unrelated pointers pointing to
    the same dynamically created object? In that case, your problem is poor
    design. The solution is to fix the design.
    [color=blue]
    >
    > 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)[/color]

    I don't know what a __vfptr is, but pointers are just pointer - they
    don't "have" anything called __vfptr. Theoretically, they could point to
    something that does, but in this case you have deleted the thing they
    point to, so you may not examine it or attempt to determine its value in
    any way. If you do so, your program's behavior is undefined.
    [color=blue]
    >
    > 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).[/color]

    Of course.
    [color=blue]
    >
    > 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.[/color]

    Of course.
    [color=blue]
    >
    > Any suggestions or recommendations on how to get the intended behavior
    > out of this snippet?[/color]

    Don't share an object between two pointers like that. Or, if you do,
    have one pointer "own" the object - never attempt to delete it through
    the other pointer. This can get complicated, though. You have to be sure
    the owner doesn't delete it while it may still be accessed through any
    other pointer.

    In general, you cannot know whether the object pointed to by a pointer
    still exists, or has been deleted, and any attempt to refer to a deleted
    object causes undefined behavior.

    -Kevin
    --
    My email address is valid, but changes periodically.
    To contact me please use the address from a recent posting.

    Comment

    • David B. Held

      #3
      Re: Deleting Pointers from STL Vector

      "Hanzo" <hanzo@milclan. com> wrote in message
      news:omhnnv4l0n fkbdv7014dovil9 4s2ang3g1@4ax.c om...
      http://www.cuj.com/documents/s=8890/...p0310alexandr/[color=blue]
      > [...]
      > Any suggestions or recommendations on how to get the intended behavior
      > out of this snippet?[/color]

      Yes. Use a smart pointer. Then, just destroy the copies of pointers that
      you don't want any more. When the last pointer to the object is destroyed,
      the object will be freed. Here's a pretty popular smart pointer:



      Dave



      ---
      Outgoing mail is certified Virus Free.
      Checked by AVG anti-virus system (http://www.grisoft.com).
      Version: 6.0.521 / Virus Database: 319 - Release Date: 9/23/2003


      Comment

      • Peter van Merkerk

        #4
        Re: Deleting Pointers from STL Vector

        > I'm iterating over a vector of base class pointers and deleting those[color=blue]
        > 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::RemoveDe adObjects()
        > {
        > // cleanup crew!!
        > vector<CDrawabl eObject*>::iter ator i;
        >
        > for (i = g_vecGameObject s.begin(); i !=
        > g_vecGameObject s.end();)
        > {
        > // if object is not null and can be removed...
        > if ((*i) && (*i)->CanRemove())
        > {
        > // grab hold before erasure
        > CDrawableObject * toDie = *i;
        >
        > // erase...
        > i = g_vecGameObject s.erase(i);
        >
        > // ...and kill
        > delete toDie;
        > toDie = NULL;
        > }
        > else
        > ++i;
        > }
        > }
        >
        > Here's the problem: on the two lines that say delete toDie; toDie =
        > NULL;[/color]

        After those lines toDie runs out of scope; why bother setting it to
        NULL?
        [color=blue]
        > I am noticing that the original variable to which toDie is
        > pointing is not being set to NULL, just "toDie" itself.[/color]

        'toDie = NULL;' only sets the toDie pointer to NULL it does not affect
        the object it was pointing to. Note that that object no longer exists at
        the point toDie is being set to NULL because it was deleted just before
        that line.

        --
        Peter van Merkerk
        peter.van.merke rk(at)dse.nl





        [ See http://www.gotw.ca/resources/clcm.htm for info about ]
        [ comp.lang.c++.m oderated. First time posters: Do this! ]

        Comment

        • Hanzo

          #5
          Re: Deleting Pointers from STL Vector

          On Thu, 02 Oct 2003 18:58:44 GMT, Kevin Goodsell
          <usenet1.spamfr ee.fusion@never box.com> wrote:
          [color=blue]
          >[Cross-post to moderated group removed. I'd rather not wait for
          >moderation. Generally, you should not cross-post to moderated groups.][/color]

          Sorry about that.
          [color=blue]
          >Why bother setting this to NULL when it's about to go out of scope and
          >cease to exist?[/color]

          The goal is to have m_cdPlayer1 set to NULL; my only access to it at
          that point is via an iterator walking the g_vecGameObject s vector,
          though.
          [color=blue]
          >delete *i;
          >i = g_vecGameObject s.erase(i);[/color]

          Several people have recommended this strategy now, I just want to make
          sure that, ultimately, m_cdPlayer1 is the variable that is deleted/set
          to NULL, so that later on in the code, when I need to perform this
          check:

          if (m_cdPlayer != NULL)

          That I don't erroneously evaluate to true when in fact the variable
          has been deleted and *should* be NULL.

          - Hanzo

          Comment

          • Randy Maddox

            #6
            Re: Deleting Pointers from STL Vector

            Hanzo <hanzo@milclan. com> wrote in message news:<omhnnv4l0 nfkbdv7014dovil 94s2ang3g1@4ax. com>...[color=blue]
            > 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::RemoveDe adObjects()
            > {
            > // cleanup crew!!
            > vector<CDrawabl eObject*>::iter ator i;
            >
            > for (i = g_vecGameObject s.begin(); i !=
            > g_vecGameObject s.end();)
            > {
            > // if object is not null and can be removed...
            > if ((*i) && (*i)->CanRemove())
            > {
            > // grab hold before erasure
            > CDrawableObject * toDie = *i;[/color]

            Here toDie is a COPY of the pointer referenced by the iterator i.
            When you later set toDie to NULL (and why not just 0?) you are only
            setting that copy, and of course not the original pointer it was
            copied from.

            All you need to do is to make toDie be a reference to the pointer of
            interest, rather than a copy of it. Simply change the above
            declaration to:

            CDrawableObject * &toDie = *i;

            and all will work as you expect.

            Randy.
            [color=blue]
            >
            > // erase...
            > i = g_vecGameObject s.erase(i);
            >
            > // ...and kill
            > delete toDie;
            > toDie = NULL;
            > }[/color]

            { Snip of unreferenced quoting. -mod/jep }

            [ See http://www.gotw.ca/resources/clcm.htm for info about ]
            [ comp.lang.c++.m oderated. First time posters: Do this! ]

            Comment

            • Bob Bell

              #7
              Re: Deleting Pointers from STL Vector

              Hanzo <hanzo@milclan. com> wrote in message news:<omhnnv4l0 nfkbdv7014dovil 94s2ang3g1@4ax. com>...[color=blue]
              > 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::RemoveDe adObjects()
              > {
              > // cleanup crew!!
              > vector<CDrawabl eObject*>::iter ator i;
              >
              > for (i = g_vecGameObject s.begin(); i !=
              > g_vecGameObject s.end();)
              > {
              > // if object is not null and can be removed...
              > if ((*i) && (*i)->CanRemove())
              > {
              > // grab hold before erasure
              > CDrawableObject * toDie = *i;
              >
              > // erase...
              > i = g_vecGameObject s.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.
              >
              > In other words, if one of the CDrawableObject s* 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)
              >
              > 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).
              >
              > 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?[/color]

              Put boost::shared_p trs in your vector (no delete needed, just erase
              from the vector), and use boost::weak_ptr as m_cdPlayer1. That should
              do what you want.

              http://www.boost.org.

              Bob

              [ See http://www.gotw.ca/resources/clcm.htm for info about ]
              [ comp.lang.c++.m oderated. First time posters: Do this! ]

              Comment

              • Hanzo

                #8
                Re: Deleting Pointers from STL Vector

                On 2 Oct 2003 19:44:52 -0400, rmaddox@isicns. com (Randy Maddox) wrote:
                [color=blue]
                >Hanzo <hanzo@milclan. com> wrote in message news:<omhnnv4l0 nfkbdv7014dovil 94s2ang3g1@4ax. com>...
                >All you need to do is to make toDie be a reference to the pointer of
                >interest, rather than a copy of it. Simply change the above
                >declaration to:
                >
                > CDrawableObject * &toDie = *i;
                >
                >and all will work as you expect.[/color]

                This does not work.

                1. toDie is set to 0x00000000 after the delete and assignment to NULL.
                m_cdPlayer1, while pointing to 0xFEEEFEEE, is still a value of
                0x00a72498. This evaluates to not NULL, and fails a test to see if it
                exists.

                2. Some other people have suggested I do this:

                if ((*i) && (*i)->CanRemove())
                {
                delete *i;
                *i = NULL;

                This, also, does not work. After the delete, both *i and m_cdPlayer1
                point to 0xFEEEFEEE (deleted), and their values are both 0x00a72498.
                However, after *i is assigned to NULL, its value is 0x00000000, while
                m_cdPlayer1 remains 0x00a72498.

                Ultimately, this boils down to one fact: I absolutely need a way to
                walk a vector of base pointers, and delete/NULL them, affecting the
                original variables that were pushed onto the vector in the first
                place.

                Some people have also suggested smart pointers and boost, and I am
                stuck with STLPort. Sorry.

                - Hanzo

                Comment

                • \Philipp Bachmann\

                  #9
                  Re: Deleting Pointers from STL Vector

                  > void CGame::RemoveDe adObjects()[color=blue]
                  > {
                  > // cleanup crew!!
                  > vector<CDrawabl eObject*>::iter ator i;
                  >
                  > for (i = g_vecGameObject s.begin(); i !=
                  > g_vecGameObject s.end();)
                  > {
                  > // if object is not null and can be removed...
                  > if ((*i) && (*i)->CanRemove())
                  > {
                  > // grab hold before erasure
                  > CDrawableObject * toDie = *i;
                  >
                  > // erase...
                  > i = g_vecGameObject s.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.[/color]

                  Yes, because you "delete" the object both "toDie" and your vector
                  element points to, but modify only the (automatic) poiter "toDie". As
                  usual with pointers, there's a difference between the pointer and the value /
                  instance it points to. So it has not much to do with "std::vecto r<>" nor with
                  C++.
                  [color=blue]
                  > In other words, if one of the CDrawableObject s* was say, a member var
                  > of CGame called m_cdPlayer1, when the delete/set-to-NULL happens:[/color]

                  Do you mean, that "m_cdPlayer 1" is an instance, not a pointer? If so, you
                  cannot achieve your goal. So "m_cdPlayer 1" _must_ be a pointer.
                  [color=blue]
                  > Any suggestions or recommendations on how to get the intended behavior
                  > out of this snippet?[/color]

                  The misconception is, that "vector<CDrawab leObject*>" is the wrong type for
                  your usage. You should store pointers to (member) pointers instead like this:
                  "vector< CDrawableObject s *CGame::* > v;"
                  Now "delete myGame.*v[42]; myGame.*v[42]=0;"
                  will do the trick.

                  In other words, you need one further indirection in addressing.

                  Cheers,
                  Philipp.





                  [ See http://www.gotw.ca/resources/clcm.htm for info about ]
                  [ comp.lang.c++.m oderated. First time posters: Do this! ]

                  Comment

                  • Antoun Kanawati

                    #10
                    Re: Deleting Pointers from STL Vector

                    Hanzo wrote:[color=blue]
                    > 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::RemoveDe adObjects()
                    > {
                    > // cleanup crew!!
                    > vector<CDrawabl eObject*>::iter ator i;
                    >
                    > for (i = g_vecGameObject s.begin(); i !=
                    > g_vecGameObject s.end();)
                    > {
                    > // if object is not null and can be removed...
                    > if ((*i) && (*i)->CanRemove())
                    > {
                    > // grab hold before erasure
                    > CDrawableObject * toDie = *i;
                    >
                    > // erase...
                    > i = g_vecGameObject s.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.
                    >
                    > In other words, if one of the CDrawableObject s* 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)
                    >
                    > 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).
                    >
                    > 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?[/color]

                    Try working with vector<CDrawabl eObject **>. This has enough
                    indirection to give you the "desired" effect. You'll need to
                    write:

                    delete *toDie;
                    *toDie = NULL;


                    Having said that, the real problem appears to be a misunderstandin g
                    of pointers and indirection.

                    The variable toDie is a local variable, the assignment 'toDie = NULL'
                    merely sets that variable to NULL. A different variable, of the
                    same type and value (m_cdPlayer) is not affected at all. However,
                    due to the interpretation of the type (pointer to CDrawableObject ),
                    and the statement 'delete toDie;' the variable m_cdPlayer holds a
                    value that is no longer valid.

                    The expectation that 'toDie = NULL' will affect any other variable,
                    under the conditions stated above, indicates a misunderstandin g of
                    pointer indirection and iterators.

                    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
                    [ comp.lang.c++.m oderated. First time posters: Do this! ]

                    Comment

                    • Marc Schellens

                      #11
                      Re: Deleting Pointers from STL Vector

                      > I'm iterating over a vector of base class pointers and deleting those[color=blue]
                      > 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::RemoveDe adObjects()
                      > {
                      > // cleanup crew!!
                      > vector<CDrawabl eObject*>::iter ator i;
                      >
                      > for (i = g_vecGameObject s.begin(); i !=
                      > g_vecGameObject s.end();)
                      > {
                      > // if object is not null and can be removed...
                      > if ((*i) && (*i)->CanRemove())
                      > {
                      > // grab hold before erasure
                      > CDrawableObject * toDie = *i;
                      >
                      > // erase...
                      > i = g_vecGameObject s.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.
                      >[/color]
                      {over quote snipped -mod}[color=blue]
                      >
                      > Any suggestions or recommendations on how to get the intended behavior
                      > out of this snippet?[/color]

                      setting toDie = NULL is useless as it get overwritten in the next
                      iteration and it is unkown outside the block is is declared in anyway.

                      setting (*i) to NULL marks at least in your vector that the element is
                      deleted.
                      If the only pointer is in your vector, you are there. But as you
                      describe it, that is not the case.

                      Realize that you deleting an object does not change any pointer to that
                      object.
                      Probably you need to rewrite some of your program.
                      One possible solution would be to keep all pointers to your objects in
                      only one vector and using iterators to this vector to access them.

                      hdh,
                      marc







                      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
                      [ comp.lang.c++.m oderated. First time posters: Do this! ]

                      Comment

                      • John Potter

                        #12
                        Re: Deleting Pointers from STL Vector

                        On 2 Oct 2003 06:18:39 -0400, Hanzo <hanzo@milclan. com> wrote:
                        [color=blue]
                        > void CGame::RemoveDe adObjects()
                        > {
                        > // cleanup crew!!
                        > vector<CDrawabl eObject*>::iter ator i;
                        >
                        > for (i = g_vecGameObject s.begin(); i !=
                        > g_vecGameObject s.end();)
                        > {
                        > // if object is not null and can be removed...
                        > if ((*i) && (*i)->CanRemove())
                        > {
                        > // grab hold before erasure
                        > CDrawableObject * toDie = *i;
                        >
                        > // erase...
                        > i = g_vecGameObject s.erase(i);[/color]

                        This removes the pointer from the vector. Since we are about
                        to delete the pointee, ownership by the vector is assumed. The
                        whole point of this exercise is that

                        delete **i;
                        i = g_vecGameObject s.erase(i);

                        may have undefined behavior because we do not know what might be
                        done with the invalid pointer by erase. Paranoid code.
                        [color=blue]
                        > // ...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.[/color]

                        The original variable of type pointer which had the same value as
                        toDie has been erased from the vector and does not exist.
                        [color=blue]
                        > In other words, if one of the CDrawableObject s* was say, a member var
                        > of CGame called m_cdPlayer1, when the delete/set-to-NULL happens:[/color]

                        If that is true, there is an ownership problem and the whole program
                        is a total mess. The CDrawableObject s* is a pointer to an object

                        allowcated on the heap and owned by that pointer. If there are any
                        other pointers to that heap object, it is a bug in the program.

                        John

                        [ See http://www.gotw.ca/resources/clcm.htm for info about ]
                        [ comp.lang.c++.m oderated. First time posters: Do this! ]

                        Comment

                        • Manuel

                          #13
                          Re: Deleting Pointers from STL Vector

                          "Hanzo" <hanzo@milclan. com> a écrit:
                          [color=blue]
                          > 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::RemoveDe adObjects()
                          > {
                          > // cleanup crew!!
                          > vector<CDrawabl eObject*>::iter ator i;
                          >
                          > for (i = g_vecGameObject s.begin(); i !=
                          > g_vecGameObject s.end();)
                          > {
                          > // if object is not null and can be removed...
                          > if ((*i) && (*i)->CanRemove())
                          > {
                          > // grab hold before erasure
                          > CDrawableObject * toDie = *i;[/color]

                          possible fix...
                          CDrawableObject *& toDie = *i;
                          [color=blue]
                          >
                          > // erase...
                          > i = g_vecGameObject s.erase(i);
                          >
                          > // ...and kill
                          > delete toDie;
                          > toDie = NULL;
                          > }
                          > else
                          > ++i;
                          > }
                          > }[/color]
                          [snip]

                          cheers,

                          - Manuel
                          to reply, swap the name with the domain.





                          [ See http://www.gotw.ca/resources/clcm.htm for info about ]
                          [ comp.lang.c++.m oderated. First time posters: Do this! ]

                          Comment

                          • Jorge Schramm

                            #14
                            Re: Deleting Pointers from STL Vector

                            Hi Hanzo,

                            if you want to manipulate the _original_ pointer m_cdPlayer, you must use a
                            vector of pointers to pointers:

                            void CGame::RemoveDe adObjects()
                            {
                            // cleanup crew!!
                            vector<CDrawabl eObject**>::ite rator i;

                            for (i = g_vecGameObject s.begin(); i != g_vecGameObject s.end();)
                            {
                            // if object is not null and can be removed...
                            if ((**i) && (**i)->CanRemove())
                            {
                            delete **i;
                            **i = NULL;

                            i = g_vecGameObject s.erase(i);
                            }
                            else
                            ++i;
                            }
                            }


                            Hope this helps
                            Jorge

                            [ See http://www.gotw.ca/resources/clcm.htm for info about ]
                            [ comp.lang.c++.m oderated. First time posters: Do this! ]

                            Comment

                            • Aaron Bentley

                              #15
                              Re: Deleting Pointers from STL Vector

                              Hanzo wrote:
                              [color=blue]
                              > 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::RemoveDe adObjects()
                              > {
                              > // cleanup crew!!
                              > vector<CDrawabl eObject*>::iter ator i;
                              >
                              > for (i = g_vecGameObject s.begin(); i !=
                              > g_vecGameObject s.end();)
                              > {
                              > // if object is not null and can be removed...
                              > if ((*i) && (*i)->CanRemove())
                              > {
                              > // grab hold before erasure
                              > CDrawableObject * toDie = *i;
                              >
                              > // erase...
                              > i = g_vecGameObject s.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.[/color]

                              Right. ToDie is just a plain pointer. You initialized it with the
                              value of (*i), then changed its value.

                              Personally, I'd rewrite it so you don't reset i immediately:[color=blue]
                              > if ((*i) && (*i)->CanRemove())
                              > {
                              > // erase...
                              > Vector<CDrawabl eObject*>::iter ator i2 =[/color]
                              g_vecGameObject s.erase(i);[color=blue]
                              >
                              > // ...and kill
                              > delete *i;
                              > *i = NULL;[/color]
                              i=i2;[color=blue]
                              > }[/color]

                              But the way to do what you want is a reference-to-pointer:

                              if ((*i) && (*i)->CanRemove())
                              {
                              // grab hold before erasure
                              CDrawableObject *& toDie = *i; //note ampersand

                              // erase...
                              i = g_vecGameObject s.erase(i);

                              // ...and kill
                              delete toDie;
                              toDie = NULL;
                              }
                              --
                              Aaron Bentley


                              [ See http://www.gotw.ca/resources/clcm.htm for info about ]
                              [ comp.lang.c++.m oderated. First time posters: Do this! ]

                              Comment

                              Working...