STL function REMOVE doesn't work

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

    STL function REMOVE doesn't work

    Hello!

    I have some problem with STL function remove

    I have two classes called Handle which is a template class and Integer which
    is not a template class. The Integer class is just a wrapper class for a
    primitive int with some methods. I don't show the Integer class because it
    will not add any information to my problem. Main is using some STL function

    Now to my problem.
    If I do this sequence in main first create two Handle object myh1 and myh2.
    Then I use push_front to first push in myh1 and then myh2 into the list
    Then I use the STL function for_each in this way
    for_each(myList 1.begin(), myList1.end(), handle_t() );
    The function operator would write 2 and then 1 because I pushed_front the
    Handle myh1 and then myh2

    This function for_each will write out the entire list by calling the
    function operator defined as
    void operator()(Hand le& temp) //Funktionsanrops operator
    { cout << *temp.body << endl; }
    for each Handle in the list. The function operator will write the primitive
    ints because the wrapper class Integer has a type conversion operator that
    convert from the class Integer to an int.

    When I want to remove a Handle from the list I use the STL function remove
    in this way
    remove(myList1. begin(), myList1.end(), myh2);
    Here I remove the Handle named myh2.

    But now to the very strange thing. I would expect that the destructor for
    Handle would be called when I do the remove but it doesn't. If I want to
    write out the list after I have done the remove I use the for_each again in
    this way.
    for_each(myList 1.begin(), myList1.end(), handle_t() );
    The function operator would now write out 1 and then 1. It should only have
    written 1 because the 2 should have been removed. The other strange thing is
    that the removed 3 has been changed to 1 in some strange way that I don't
    understand.

    Have you any suggestion ?

    //Tony


    #include "handle.h"
    #include <list>
    #include <algorithm>
    using namespace std;

    typedef Handle<Integer> handle_t;

    main()
    {
    list<handle_t> myList1;
    handle_t myh1( new Integer(1) );
    handle_t myh2( new Integer(2) );

    myList1.push_fr ont(myh1);
    myList1.push_fr ont(myh2);
    for_each(myList 1.begin(), myList1.end(), handle_t());
    remove(myList1. begin(), myList1.end(), myh2);
    for_each(myList 1.begin(), myList1.end(), handle_t());
    }

    #include "integer.h"
    #include <iostream>
    using namespace std;

    template<class T>
    class Handle
    {
    public:
    Handle()
    {
    body = new T(0);
    ref_count = new int(1);
    }

    Handle(T* body_ptr) //Constructor
    {
    body = body_ptr;
    ref_count = new int(1);
    }

    ~Handle() //Destructor
    {
    (*ref_count)--;
    if (!*ref_count)
    deleteAll();
    }

    bool operator==(cons t Handle& temp)
    { return *body == *temp.body; }

    Handle(const Handle& h) //Copy constructor
    {
    body = h.body;
    ref_count = h.ref_count;
    (*ref_count)++;
    }

    void operator()(Hand le& temp) //Functionoperato r
    { cout << * temp.body << endl; }
    private:
    T* body;
    int* ref_count;

    void deleteAll()
    {
    delete body;
    body = NULL;
    delete ref_count;
    ref_count = NULL;
    }
    };


  • Achintya

    #2
    Re: STL function REMOVE doesn't work


    Tony Johansson wrote:[color=blue]
    > Hello!
    >
    > I have some problem with STL function remove
    >
    > I have two classes called Handle which is a template class and[/color]
    Integer which[color=blue]
    > is not a template class. The Integer class is just a wrapper class[/color]
    for a[color=blue]
    > primitive int with some methods. I don't show the Integer class[/color]
    because it[color=blue]
    > will not add any information to my problem. Main is using some STL[/color]
    function[color=blue]
    >
    > Now to my problem.
    > If I do this sequence in main first create two Handle object myh1 and[/color]
    myh2.[color=blue]
    > Then I use push_front to first push in myh1 and then myh2 into the[/color]
    list[color=blue]
    > Then I use the STL function for_each in this way
    > for_each(myList 1.begin(), myList1.end(), handle_t() );
    > The function operator would write 2 and then 1 because I pushed_front[/color]
    the[color=blue]
    > Handle myh1 and then myh2
    >
    > This function for_each will write out the entire list by calling the
    > function operator defined as
    > void operator()(Hand le& temp) //Funktionsanrops operator
    > { cout << *temp.body << endl; }
    > for each Handle in the list. The function operator will write the[/color]
    primitive[color=blue]
    > ints because the wrapper class Integer has a type conversion operator[/color]
    that[color=blue]
    > convert from the class Integer to an int.
    >
    > When I want to remove a Handle from the list I use the STL function[/color]
    remove[color=blue]
    > in this way
    > remove(myList1. begin(), myList1.end(), myh2);
    > Here I remove the Handle named myh2.
    >
    > But now to the very strange thing. I would expect that the destructor[/color]
    for[color=blue]
    > Handle would be called when I do the remove but it doesn't. If I want[/color]
    to[color=blue]
    > write out the list after I have done the remove I use the for_each[/color]
    again in[color=blue]
    > this way.
    > for_each(myList 1.begin(), myList1.end(), handle_t() );
    > The function operator would now write out 1 and then 1. It should[/color]
    only have[color=blue]
    > written 1 because the 2 should have been removed. The other strange[/color]
    thing is[color=blue]
    > that the removed 3 has been changed to 1 in some strange way that I[/color]
    don't[color=blue]
    > understand.
    >
    > Have you any suggestion ?
    >
    > //Tony
    >
    >
    > #include "handle.h"
    > #include <list>
    > #include <algorithm>
    > using namespace std;
    >
    > typedef Handle<Integer> handle_t;
    >
    > main()
    > {
    > list<handle_t> myList1;
    > handle_t myh1( new Integer(1) );
    > handle_t myh2( new Integer(2) );
    >
    > myList1.push_fr ont(myh1);
    > myList1.push_fr ont(myh2);
    > for_each(myList 1.begin(), myList1.end(), handle_t());
    > remove(myList1. begin(), myList1.end(), myh2);
    > for_each(myList 1.begin(), myList1.end(), handle_t());
    > }
    >
    > #include "integer.h"
    > #include <iostream>
    > using namespace std;
    >
    > template<class T>
    > class Handle
    > {
    > public:
    > Handle()
    > {
    > body = new T(0);
    > ref_count = new int(1);
    > }
    >
    > Handle(T* body_ptr) //Constructor
    > {
    > body = body_ptr;
    > ref_count = new int(1);
    > }
    >
    > ~Handle() //Destructor
    > {
    > (*ref_count)--;
    > if (!*ref_count)
    > deleteAll();
    > }
    >
    > bool operator==(cons t Handle& temp)
    > { return *body == *temp.body; }
    >
    > Handle(const Handle& h) //Copy constructor
    > {
    > body = h.body;
    > ref_count = h.ref_count;
    > (*ref_count)++;
    > }
    >
    > void operator()(Hand le& temp) //Functionoperato r
    > { cout << * temp.body << endl; }
    > private:
    > T* body;
    > int* ref_count;
    >
    > void deleteAll()
    > {
    > delete body;
    > body = NULL;
    > delete ref_count;
    > ref_count = NULL;
    > }
    > };[/color]

    Hi,

    Please post the Integer class details...

    -vs_p...

    Comment

    • Tony Johansson

      #3
      Re: STL function REMOVE doesn't work. Add the Integer class


      "Achintya" <vs_praveen@yah oo.com> skrev i meddelandet
      news:1116315618 .296766.84330@f 14g2000cwb.goog legroups.com...[color=blue]
      >
      > Tony Johansson wrote:[color=green]
      >> Hello!
      >>
      >> I have some problem with STL function remove
      >>
      >> I have two classes called Handle which is a template class and[/color]
      > Integer which[color=green]
      >> is not a template class. The Integer class is just a wrapper class[/color]
      > for a[color=green]
      >> primitive int with some methods. I don't show the Integer class[/color]
      > because it[color=green]
      >> will not add any information to my problem. Main is using some STL[/color]
      > function[color=green]
      >>
      >> Now to my problem.
      >> If I do this sequence in main first create two Handle object myh1 and[/color]
      > myh2.[color=green]
      >> Then I use push_front to first push in myh1 and then myh2 into the[/color]
      > list[color=green]
      >> Then I use the STL function for_each in this way
      >> for_each(myList 1.begin(), myList1.end(), handle_t() );
      >> The function operator would write 2 and then 1 because I pushed_front[/color]
      > the[color=green]
      >> Handle myh1 and then myh2
      >>
      >> This function for_each will write out the entire list by calling the
      >> function operator defined as
      >> void operator()(Hand le& temp) //Funktionsanrops operator
      >> { cout << *temp.body << endl; }
      >> for each Handle in the list. The function operator will write the[/color]
      > primitive[color=green]
      >> ints because the wrapper class Integer has a type conversion operator[/color]
      > that[color=green]
      >> convert from the class Integer to an int.
      >>
      >> When I want to remove a Handle from the list I use the STL function[/color]
      > remove[color=green]
      >> in this way
      >> remove(myList1. begin(), myList1.end(), myh2);
      >> Here I remove the Handle named myh2.
      >>
      >> But now to the very strange thing. I would expect that the destructor[/color]
      > for[color=green]
      >> Handle would be called when I do the remove but it doesn't. If I want[/color]
      > to[color=green]
      >> write out the list after I have done the remove I use the for_each[/color]
      > again in[color=green]
      >> this way.
      >> for_each(myList 1.begin(), myList1.end(), handle_t() );
      >> The function operator would now write out 1 and then 1. It should[/color]
      > only have[color=green]
      >> written 1 because the 2 should have been removed. The other strange[/color]
      > thing is[color=green]
      >> that the removed 3 has been changed to 1 in some strange way that I[/color]
      > don't[color=green]
      >> understand.
      >>
      >> Have you any suggestion ?
      >>
      >> //Tony
      >>
      >>
      >> #include "handle.h"
      >> #include <list>
      >> #include <algorithm>
      >> using namespace std;
      >>
      >> typedef Handle<Integer> handle_t;
      >>
      >> main()
      >> {
      >> list<handle_t> myList1;
      >> handle_t myh1( new Integer(1) );
      >> handle_t myh2( new Integer(2) );
      >>
      >> myList1.push_fr ont(myh1);
      >> myList1.push_fr ont(myh2);
      >> for_each(myList 1.begin(), myList1.end(), handle_t());
      >> remove(myList1. begin(), myList1.end(), myh2);
      >> for_each(myList 1.begin(), myList1.end(), handle_t());
      >> }
      >>
      >> #include "integer.h"
      >> #include <iostream>
      >> using namespace std;
      >>
      >> template<class T>
      >> class Handle
      >> {
      >> public:
      >> Handle()
      >> {
      >> body = new T(0);
      >> ref_count = new int(1);
      >> }
      >>
      >> Handle(T* body_ptr) //Constructor
      >> {
      >> body = body_ptr;
      >> ref_count = new int(1);
      >> }
      >>
      >> ~Handle() //Destructor
      >> {
      >> (*ref_count)--;
      >> if (!*ref_count)
      >> deleteAll();
      >> }
      >>
      >> bool operator==(cons t Handle& temp)
      >> { return *body == *temp.body; }
      >>
      >> Handle(const Handle& h) //Copy constructor
      >> {
      >> body = h.body;
      >> ref_count = h.ref_count;
      >> (*ref_count)++;
      >> }
      >>
      >> void operator()(Hand le& temp) //Functionoperato r
      >> { cout << * temp.body << endl; }
      >> private:
      >> T* body;
      >> int* ref_count;
      >>
      >> void deleteAll()
      >> {
      >> delete body;
      >> body = NULL;
      >> delete ref_count;
      >> ref_count = NULL;
      >> }
      >> };[/color]
      >
      > Hi,
      >
      > Please post the Integer class details...
      >
      > -vs_p...[/color]

      Hello!!

      Here is the Integer class

      #ifndef INTEGER_H
      #define INTEGER_H
      #include <iostream>


      class Integer
      {
      public:
      Integer()
      {}

      Integer(int value): value_(value)
      {
      copy_cnt = new int(0);
      std::cout << "Creating original:"<< value << std::endl;
      };

      Integer(const Integer& src): value_(src.valu e_), copy_cnt(src.co py_cnt)
      {
      (*copy_cnt) += 1;
      std::cout << "Creating copy:"<< *copy_cnt << " of:" << value_ <<
      std::endl;
      };

      virtual ~Integer()
      {
      if(*copy_cnt == 0)
      {
      std::cout << "Deleting last: "<< value_ << std::endl;
      delete copy_cnt;
      }
      else
      {
      (*copy_cnt) -= 1;
      std::cout << "Deleting: "<< value_ << "\t\t "<< *copy_cnt << " copies
      are left" << std::endl;
      }
      };

      const Integer& operator=(const Integer& src)
      {
      this->value_ = src.value_;
      if(*copy_cnt == 0)
      {
      delete copy_cnt;
      }
      else
      {
      (*copy_cnt) -= 1;
      }
      copy_cnt = src.copy_cnt;
      (*copy_cnt) += 1;
      return *this;
      }


      bool operator==(cons t Integer& src) const
      { return this->value_ == src.value_; }

      bool operator!=(cons t Integer& src) const
      { return this->value_ != src.value_; }

      operator int() const
      { return this->value_; }

      void setValue(int value)
      {
      this->value_ = value;
      if(*copy_cnt > 0)
      {
      *copy_cnt -= 1;
      copy_cnt = new int;
      *copy_cnt = 0;
      }
      }

      private:
      int value_;
      int *copy_cnt;
      };
      #endif[color=blue]
      >[/color]


      Comment

      • Krishanu Debnath

        #4
        Re: STL function REMOVE doesn't work

        Tony Johansson wrote:[color=blue]
        > Hello!
        >[/color]

        [snip]
        [color=blue]
        >
        > When I want to remove a Handle from the list I use the STL function remove
        > in this way
        > remove(myList1. begin(), myList1.end(), myh2);
        > Here I remove the Handle named myh2.
        >
        > But now to the very strange thing. I would expect that the destructor for
        > Handle would be called when I do the remove but it doesn't. If I want to[/color]

        Because 'remove' doesn't destory any iterator. If you print the size of
        the list 'myList1', you will see the size is still same i.e. 2. remove
        returns the iterator of 'newLast', where [myList1.begin() , newLast)
        contains no elements equal to myh2.

        If you want to 'actually' remove the myh2 from myList1, you need to call

        myList1.erase(r emove(myList1.b egin(), myList1.end(), myh2),
        myList1.end());

        [color=blue]
        > write out the list after I have done the remove I use the for_each again in
        > this way.
        > for_each(myList 1.begin(), myList1.end(), handle_t() );
        > The function operator would now write out 1 and then 1. It should only have
        > written 1 because the 2 should have been removed. The other strange thing is
        > that the removed 3 has been changed to 1 in some strange way that I don't
        > understand.[/color]

        After remove, dereferencing the iterators within range [newLast,
        myList1.end()) are legal, but the elements they point to are
        unspecified.

        Krishanu

        --
        "Automatica lly translated code seldom looks nice and is usually not
        meant to be read by humans..."
        --Jens Thoms Toerring

        Comment

        • Achintya

          #5
          Re: STL function REMOVE doesn't work


          Krishanu Debnath wrote:[color=blue]
          > Tony Johansson wrote:[color=green]
          > > Hello!
          > >[/color]
          >
          > [snip]
          >[color=green]
          > >
          > > When I want to remove a Handle from the list I use the STL function[/color][/color]
          remove[color=blue][color=green]
          > > in this way
          > > remove(myList1. begin(), myList1.end(), myh2);
          > > Here I remove the Handle named myh2.
          > >
          > > But now to the very strange thing. I would expect that the[/color][/color]
          destructor for[color=blue][color=green]
          > > Handle would be called when I do the remove but it doesn't. If I[/color][/color]
          want to[color=blue]
          >
          > Because 'remove' doesn't destory any iterator. If you print the size[/color]
          of[color=blue]
          > the list 'myList1', you will see the size is still same i.e. 2.[/color]
          remove[color=blue]
          > returns the iterator of 'newLast', where [myList1.begin() , newLast)
          > contains no elements equal to myh2.
          >
          > If you want to 'actually' remove the myh2 from myList1, you need to[/color]
          call[color=blue]
          >
          > myList1.erase(r emove(myList1.b egin(), myList1.end(), myh2),
          > myList1.end());
          >
          >[color=green]
          > > write out the list after I have done the remove I use the for_each[/color][/color]
          again in[color=blue][color=green]
          > > this way.
          > > for_each(myList 1.begin(), myList1.end(), handle_t() );
          > > The function operator would now write out 1 and then 1. It should[/color][/color]
          only have[color=blue][color=green]
          > > written 1 because the 2 should have been removed. The other strange[/color][/color]
          thing is[color=blue][color=green]
          > > that the removed 3 has been changed to 1 in some strange way that I[/color][/color]
          don't[color=blue][color=green]
          > > understand.[/color]
          >
          > After remove, dereferencing the iterators within range [newLast,
          > myList1.end()) are legal, but the elements they point to are
          > unspecified.
          >
          > Krishanu
          >
          > --
          > "Automatica lly translated code seldom looks nice and is usually not
          > meant to be read by humans..."
          > --Jens Thoms Toerring[/color]

          Hi,

          Yup,...in other words 'remove' simply moves the selected elements to
          the end of the sequence and returns an iterator to the first 'removed'
          element.

          -vs_p...

          Comment

          • Maciej Pilichowski

            #6
            Re: STL function REMOVE doesn't work

            On Tue, 17 May 2005 07:11:08 GMT, "Tony Johansson"
            <johansson.ande rsson@telia.com > wrote:
            [color=blue]
            >When I want to remove a Handle from the list I use the STL function remove
            >in this way
            >remove(myList1 .begin(), myList1.end(), myh2);
            >Here I remove the Handle named myh2.
            >
            >But now to the very strange thing. I would expect that the destructor for
            >Handle would be called when I do the remove but it doesn't.[/color]

            The name of this function is confusing -- it doesn't remove anything
            it just reorder the collection. You can think about it like the
            partition in reverse.

            Partition moves given elements to the front of the collection, remove
            -- to the back.

            1 2 3 1

            when you apply the remove function with "1" you will get:

            2 3 1 1

            And now you can apply the erase function. Good STL guide is very
            helpful, try Josuttis, it's category-killer.

            have a nice day
            bye


            --
            Maciej "MACiAS" Pilichowski http://bantu.fm.interia.pl/

            M A R G O T --> http://www.margot.cad.pl/
            automatyczny t³umacz (wczesna wersja rozwojowa) angielsko-polski

            Comment

            • Maciej Pilichowski

              #7
              Re: STL function REMOVE doesn't work

              On 17 May 2005 00:40:18 -0700, "Achintya" <vs_praveen@yah oo.com>
              wrote:
              [color=blue]
              >Please post the Integer class details...[/color]

              And you have to quote the whole message just to add those witty words?

              --
              Maciej "MACiAS" Pilichowski http://bantu.fm.interia.pl/

              M A R G O T --> http://www.margot.cad.pl/
              automatyczny t³umacz (wczesna wersja rozwojowa) angielsko-polski

              Comment

              • Rapscallion

                #8
                Re: STL function REMOVE doesn't work

                Achintya wrote:[color=blue]
                > Yup,...in other words 'remove' simply moves the selected elements to
                > the end of the sequence and returns an iterator to the first[/color]
                'removed'[color=blue]
                > element.[/color]

                No, 'remove' may also overwrite and duplicate elements (see e.g.
                Stroustrup). It's a good example of a bad interface design.

                R.C.

                Comment

                • Richard Herring

                  #9
                  Re: STL function REMOVE doesn't work

                  In message <73aj8115q0smns uev4djdlpi1ouka h7f2s@4ax.com>, Maciej
                  Pilichowski <bantu@SKASUJTO poczta.FM> writes[color=blue]
                  >On Tue, 17 May 2005 07:11:08 GMT, "Tony Johansson"
                  ><johansson.and ersson@telia.co m> wrote:
                  >[color=green]
                  >>When I want to remove a Handle from the list I use the STL function remove
                  >>in this way
                  >>remove(myList 1.begin(), myList1.end(), myh2);
                  >>Here I remove the Handle named myh2.
                  >>
                  >>But now to the very strange thing. I would expect that the destructor for
                  >>Handle would be called when I do the remove but it doesn't.[/color]
                  >
                  >The name of this function is confusing -- it doesn't remove anything
                  >it just reorder the collection. You can think about it like the
                  >partition in reverse.
                  >
                  >Partition moves given elements to the front of the collection, remove
                  >-- to the back.[/color]

                  Not quite. After calling partition() you have exactly the same elements,
                  in a different order. All elements are preserved.

                  After remove(), the back of the sequence contains garbage - a mixture of
                  unwanted elements and _copies_ of the wanted ones. There's no guarantee
                  that the unwanted elements are preserved.
                  [color=blue]
                  >1 2 3 1
                  >
                  >when you apply the remove function with "1" you will get:
                  >
                  >2 3 1 1[/color]

                  I suspect you'll actually get 2 3 3 1
                  [color=blue]
                  >
                  > And now you can apply the erase function. Good STL guide is very
                  >helpful, try Josuttis, it's category-killer.
                  >
                  >have a nice day
                  >bye
                  >
                  >[/color]

                  --
                  Richard Herring

                  Comment

                  • Mark P

                    #10
                    Re: STL function REMOVE doesn't work

                    Tony Johansson wrote:[color=blue]
                    > Hello!
                    >
                    > I have some problem with STL function remove
                    >[/color]

                    This is discussed in Meyer's Effective STL and also in footnote [1] of


                    Note in particular the erase-remove idiom which may be what you're
                    looking for.

                    Mark

                    Comment

                    • Maciej Pilichowski

                      #11
                      Re: STL function REMOVE doesn't work

                      On Tue, 17 May 2005 10:07:37 +0100, Richard Herring <junk@[127.0.0.1]>
                      wrote:
                      [color=blue]
                      >After remove(), the back of the sequence contains garbage - a mixture of
                      >unwanted elements and _copies_ of the wanted ones. There's no guarantee
                      >that the unwanted elements are preserved.[/color]

                      Thank you for pointing that out -- I tried too hard to make an
                      analogy, sorry ;-)

                      Kind regards,

                      --
                      Maciej "MACiAS" Pilichowski http://bantu.fm.interia.pl/

                      M A R G O T --> http://www.margot.cad.pl/
                      automatyczny t³umacz (wczesna wersja rozwojowa) angielsko-polski

                      Comment

                      • msalters

                        #12
                        Re: STL function REMOVE doesn't work


                        Rapscallion wrote:[color=blue]
                        > Achintya wrote:[color=green]
                        > > Yup,...in other words 'remove' simply moves the selected elements[/color][/color]
                        to[color=blue][color=green]
                        > > the end of the sequence and returns an iterator to the first[/color]
                        > 'removed'[color=green]
                        > > element.[/color]
                        >
                        > No, 'remove' may also overwrite and duplicate elements (see e.g.
                        > Stroustrup). It's a good example of a bad interface design.[/color]

                        It's a good example of generic design. The domain on which
                        the STL works is ranges, not containers. You simply cannot
                        remove elements from a char[20]. However, you can create
                        a subrange within the char[20] that has the desired property. By
                        definition, you're not interested in the
                        remainder, or you'd use remove_copy/copy_if

                        HTH,
                        Michiel Salters

                        Comment

                        Working...