472,811 Members | 1,115 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,811 software developers and data experts.

Question about STL erase function

In Effective STL item 9 "Choose carefully among erasing options", it
has this example:

bool badValue(int x); // returns whether x is 'bad'
c.erase ( remove_if(c.begin(), c.end(), badValue), c.end()); // this
is the best way to get rid of objects where badValue returns true when
c is a vector, string, or dequeue

c.remove_if(badValue); // this is the best way to get rid of objects
where badValue returns true when c is a list

My question is "For the first case, why we need to call c.erase() again
and pass in the return value of remove_if()?" Doesn't the call to
remove_if() remove the item from the container (in this case a vector)?
why we need to call erase() again?

Thank you.

Jan 18 '06 #1
10 5008
Piotr wrote:
In Effective STL item 9 "Choose carefully among erasing options", it
has this example:

bool badValue(int x); // returns whether x is 'bad'
c.erase ( remove_if(c.begin(), c.end(), badValue), c.end()); // this
is the best way to get rid of objects where badValue returns true when
c is a vector, string, or dequeue

c.remove_if(badValue); // this is the best way to get rid of objects
where badValue returns true when c is a list

My question is "For the first case, why we need to call c.erase() again
and pass in the return value of remove_if()?" Doesn't the call to
remove_if() remove the item from the container (in this case a vector)?
why we need to call erase() again?


I believe the book you are reading has the answer to your question.
std::remove_if does not change the size of the container - it couldn't,
since you are only passing it a range specified by two iterators.
Instead, it returns a new iterator indicating the new end of the range.

See here for an explanation:

http://www.sgi.com/tech/stl/remove_if.html

Best regards,

Tom

Jan 18 '06 #2
"Piotr" <ra************@gmail.com> schrieb im Newsbeitrag
news:11**********************@z14g2000cwz.googlegr oups.com...
In Effective STL item 9 "Choose carefully among erasing options", it
has this example:

bool badValue(int x); // returns whether x is 'bad'
c.erase ( remove_if(c.begin(), c.end(), badValue), c.end()); // this
is the best way to get rid of objects where badValue returns true when
c is a vector, string, or dequeue

c.remove_if(badValue); // this is the best way to get rid of objects
where badValue returns true when c is a list

My question is "For the first case, why we need to call c.erase() again
and pass in the return value of remove_if()?" Doesn't the call to
remove_if() remove the item from the container (in this case a vector)?
why we need to call erase() again?


remove_if(first, last, pred) removes unwanted elements from the sequence
[first, last) and it copies the remaining elements to the places of the
removed elements. But it does not actually discard unused space from the end
of the sequence. For each element removed, you get a copy of another
element. Basically remove_if does something like

iterator free = first;
while (first != last)
{
if (badValue(*first))
++first;
else
*free++ = *first++;
}
return free;

HTH
Heinz
Jan 18 '06 #3
Piotr wrote:

My question is "For the first case, why we need to call c.erase() again
and pass in the return value of remove_if()?" Doesn't the call to
remove_if() remove the item from the container (in this case a vector)?
why we need to call erase() again?


Algorithms work on sequences designated by pairs of iterators. They do
not work on containers. remove_if "removes" elements from the sequence
that's passed to it by copying replacement elements on top of rejected
ones, and giving back a new end iterator that designates the end of the
new sequence. Typically that sequence is shorter than the original one,
and any elements pointed to by the end iterator and beyond are
irrelevant to the algorithm.

The algorithm doesn't know anything about the source of the sequence,
and cannot modify a container that might have been the source of the
sequence that was passed to it. But because it rearranges elements, you
can use the end iterator that it returns to tell you where the remaining
elements are in your container: they're the ones from the end iterator
returned by the algorithm to the actual end of the container. So you
erase 'em if that's appropriate.

If I haven't made too many typos, try this:

int data[] = { 1, 2, 3, 4, 5, 6, 7 }

struct is_odd
{
bool operator()(int val)
{
return val & 1;
}
};

int main()
{
int *begin = data;
int *end = data + sizeof(data) / sizeof(*data);

std::cout << "Original sequence: ";
std::copy(begin, end, std::ostream_iterator<int>(std::cout, " ");
std::cout << '\n';

int *new_end = std::remove_if(begin, end, is_odd());
// nothing to erase, 'cause the container's size is fixed

std::cout << "Modified sequence: ";
std::copy(begin, new_end, std::ostream_iterator<int>(std::cout, " ");
std::cout << '\n';

std::cout << "Original container: ";
std::copy(begin, end, std::ostream_iterator<int>(std::cout, " ");
std::cout << '\n';

return 0;
}

Now modify it to use a vector<int> instead of an array.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jan 18 '06 #4
Thanks.
But why I don't need to do that for list?

Jan 19 '06 #5
Piotr wrote:
Thanks.
But why I don't need to do that for list?


Well, to quote your example (assume vec is a std::vector and list is a
std::list):

bool badValue(int x);

vec.erase(std::remove_if(vec.begin(),
vec.end(),
badValue), vec.end());

list.remove_if(badValue);

In the vector example, you are using an algorithm, std::remove_if. In
the list example, you are using a std::list member function,
std::list::remove_if. The algorithm does not erase the removed
elements. The list member function does erase the removed elements.
In other words, the algorithm and the member function are not the same.

If you can, get yourself a copy of Josuttis's The C++ Standard Library.
It is an excellent resource, and will answer all of your questions
like this.

Best regards,

Tom

Jan 19 '06 #6
Piotr wrote:
Thanks.
But why I don't need to do that for list?

Do what? Please quote.

--
Ian Collins.
Jan 19 '06 #7
Piotr wrote:
Thanks.
But why I don't need to do that for list?


Because list::remove_if is a member function of the template. Unlike the
standalone algorithm, it knows that it's working on a container.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jan 19 '06 #8
After the return of remove_if() to remove elements from the container
which matches the condition, how can I get the address of all the
removed elements and call their destructor?

Thank you.

Jan 19 '06 #9

Piotr wrote:
After the return of remove_if() to remove elements from the container
which matches the condition, how can I get the address of all the
removed elements and call their destructor?


Which remove_if() are you referring to? If you are referring to the
algorithm std::remove_if, then calling erase() as you showed in your
original example will results in the removed elements' destructors
being called automatically.

If you are referring to the std::list member function remove_if, that
function will result in the removed elements' destructors being called
automatically.

In neither case you should you explicitly call the elements'
destructors yourself.

Best regards,

Tom

Jan 19 '06 #10
In message <11**********************@g47g2000cwa.googlegroups .com>,
Piotr <ra************@gmail.com> writes
After the return of remove_if() to remove elements from the container
which matches the condition, how can I get the address of all the
removed elements and call their destructor?

No need. container.erase(remove_if(/*...*/), container.end()) will do
it for you.

(Note that the sequence bounded by remove_if() and container.end() is
stuff you no longer need, but not necessarily "the removed elements",
since some of the unwanted elements may have had wanted ones copied into
them.)

--
Richard Herring
Jan 19 '06 #11

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

10
by: Pat | last post by:
Hi, I use "vector<int> v" in my program. If "v" contains the following: (front) 1 2 3 4 2 5 7 1 (end), I want to remove some element, say "2", and I want the resultant "v" to be as follows:...
7
by: Randy Yates | last post by:
OK, why doesn't this work: string EraseCommas(string &numericString) { UINT16_T commaPosition; commaPosition = numericString.find(","); while (commaPosition != string::npos); {
10
by: vikas | last post by:
how can I make getline(cin, somestring) make skip initial white spaces, say if i enter " a" length should be 1. why do i need to hit enter twice after getline to display what i got? how to over...
20
by: Tom van Stiphout | last post by:
I'm about to write a function like below, which I'm going to call a lot of times. So I care about possible memory leaks. I think whether I should use Erase or not depends on whether Split creates...
8
by: Jim Langston | last post by:
There's the thing about iterating though a map or vector when you may delete one of the elements, where you simply assign the iterator to the map.erase() statement or increment it if you don't. ...
8
by: olanglois | last post by:
Hi, I was asking myself to following question. What is better to erase an element from a STL map: calling (option #1) size_type erase(const key_type& k) or calling (option #2)
6
by: catphive.lists | last post by:
Is there a way to call erase(iter) on a list without invalidating the iterator? Can I make a copy of an iterator and then move forward the original without moving the copy? I'm aware of the...
5
by: subramanian100in | last post by:
Suppose I have vector<intcontainer; Suppose I store some values into "container". Suppose that "left" and "right" are valid iterators into "container" and that "right" is NOT...
0
by: subramanian100in | last post by:
Suppose I have vector<intc; for (int i = 0; i < 10; ++i) c.push_back(i); vector<int>::iterator it = find(c.begin(), c.end(), 5); If I do, c.insert(c.begin(), 10);
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 2 August 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM) The start time is equivalent to 19:00 (7PM) in Central...
0
linyimin
by: linyimin | last post by:
Spring Startup Analyzer generates an interactive Spring application startup report that lets you understand what contributes to the application startup time and helps to optimize it. Support for...
0
by: erikbower65 | last post by:
Here's a concise step-by-step guide for manually installing IntelliJ IDEA: 1. Download: Visit the official JetBrains website and download the IntelliJ IDEA Community or Ultimate edition based on...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Sept 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM) The start time is equivalent to 19:00 (7PM) in Central...
0
by: Taofi | last post by:
I try to insert a new record but the error message says the number of query names and destination fields are not the same This are my field names ID, Budgeted, Actual, Status and Differences ...
14
DJRhino1175
by: DJRhino1175 | last post by:
When I run this code I get an error, its Run-time error# 424 Object required...This is my first attempt at doing something like this. I test the entire code and it worked until I added this - If...
0
by: Rina0 | last post by:
I am looking for a Python code to find the longest common subsequence of two strings. I found this blog post that describes the length of longest common subsequence problem and provides a solution in...
0
by: lllomh | last post by:
Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{
2
by: DJRhino | last post by:
Was curious if anyone else was having this same issue or not.... I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.