By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
432,384 Members | 845 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 432,384 IT Pros & Developers. It's quick & easy.

STL function REMOVE doesn't work

P: n/a
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(myList1.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()(Handle& temp) //Funktionsanropsoperator
{ 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(myList1.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_front(myh1);
myList1.push_front(myh2);
for_each(myList1.begin(), myList1.end(), handle_t());
remove(myList1.begin(), myList1.end(), myh2);
for_each(myList1.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==(const Handle& temp)
{ return *body == *temp.body; }

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

void operator()(Handle& temp) //Functionoperator
{ cout << * temp.body << endl; }
private:
T* body;
int* ref_count;

void deleteAll()
{
delete body;
body = NULL;
delete ref_count;
ref_count = NULL;
}
};
Jul 23 '05 #1
Share this Question
Share on Google+
11 Replies


P: n/a

Tony Johansson wrote:
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(myList1.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()(Handle& temp) //Funktionsanropsoperator
{ 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(myList1.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_front(myh1);
myList1.push_front(myh2);
for_each(myList1.begin(), myList1.end(), handle_t());
remove(myList1.begin(), myList1.end(), myh2);
for_each(myList1.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==(const Handle& temp)
{ return *body == *temp.body; }

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

void operator()(Handle& temp) //Functionoperator
{ cout << * temp.body << endl; }
private:
T* body;
int* ref_count;

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


Hi,

Please post the Integer class details...

-vs_p...

Jul 23 '05 #2

P: n/a

"Achintya" <vs********@yahoo.com> skrev i meddelandet
news:11*********************@f14g2000cwb.googlegro ups.com...

Tony Johansson wrote:
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(myList1.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()(Handle& temp) //Funktionsanropsoperator
{ 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(myList1.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_front(myh1);
myList1.push_front(myh2);
for_each(myList1.begin(), myList1.end(), handle_t());
remove(myList1.begin(), myList1.end(), myh2);
for_each(myList1.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==(const Handle& temp)
{ return *body == *temp.body; }

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

void operator()(Handle& temp) //Functionoperator
{ cout << * temp.body << endl; }
private:
T* body;
int* ref_count;

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


Hi,

Please post the Integer class details...

-vs_p...


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.value_), copy_cnt(src.copy_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==(const Integer& src) const
{ return this->value_ == src.value_; }

bool operator!=(const 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

Jul 23 '05 #3

P: n/a
Tony Johansson wrote:
Hello!

[snip]

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
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(remove(myList1.begin(), myList1.end(), myh2),
myList1.end());

write out the list after I have done the remove I use the for_each again in
this way.
for_each(myList1.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.


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

Krishanu

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

Jul 23 '05 #4

P: n/a

Krishanu Debnath wrote:
Tony Johansson wrote:
Hello!

[snip]

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
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(remove(myList1.begin(), myList1.end(), myh2),
myList1.end());

write out the list after I have done the remove I use the for_each

again in this way.
for_each(myList1.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.


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

Krishanu

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


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

Jul 23 '05 #5

P: n/a
On Tue, 17 May 2005 07:11:08 GMT, "Tony Johansson"
<jo*****************@telia.com> wrote:
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.


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
Jul 23 '05 #6

P: n/a
On 17 May 2005 00:40:18 -0700, "Achintya" <vs********@yahoo.com>
wrote:
Please post the Integer class details...


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
Jul 23 '05 #7

P: n/a
Achintya wrote:
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.


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

R.C.

Jul 23 '05 #8

P: n/a
In message <73********************************@4ax.com>, Maciej
Pilichowski <ba***@SKASUJTOpoczta.FM> writes
On Tue, 17 May 2005 07:11:08 GMT, "Tony Johansson"
<jo*****************@telia.com> wrote:
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.
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.


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.
1 2 3 1

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

2 3 1 1
I suspect you'll actually get 2 3 3 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


--
Richard Herring
Jul 23 '05 #9

P: n/a
Tony Johansson wrote:
Hello!

I have some problem with STL function remove


This is discussed in Meyer's Effective STL and also in footnote [1] of
http://www.sgi.com/tech/stl/remove.html

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

Mark
Jul 23 '05 #10

P: n/a
On Tue, 17 May 2005 10:07:37 +0100, Richard Herring <ju**@[127.0.0.1]>
wrote:
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.


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
Jul 23 '05 #11

P: n/a

Rapscallion wrote:
Achintya wrote:
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.


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


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

Jul 23 '05 #12

This discussion thread is closed

Replies have been disabled for this discussion.