Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

STL "erase-remove" idiom: Why not "resize-remove"?

It is commonly understood that a good way to fully delete desired items from a std::vector is the erase-remove idiom.

As noted in the above link (as of the date of this posting), in code the erase-remove idiom looks like this:

int main()
{
  // initialises a vector that holds the numbers from 0-9.
  std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

  // erase-remove idiom to completely eliminate the desired items from the vector
  v.erase( std::remove( std::begin(v), std::end(v), 5 ), std::end(v) ); 
}

I would like to know whether a resize-remove idiom is equivalent in terms of functionality and performance to the erase-remove idiom. Or, perhaps I am missing something obvious?

Is the following resize-remove idiom equivalent to the above erase-remove idiom?

int main()
{
  std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

  // Is this "resize-remove" approach equivalent to the "erase-remove" idiom?
  v.resize( std::remove( std::begin(v), std::end(v), 5 ) - v.begin() ); 
}
like image 810
Dan Nissenbaum Avatar asked Apr 04 '14 10:04

Dan Nissenbaum


4 Answers

In my opinion, there are two reasons:

  1. std::remove algorithm requires only Forward Iterator, but - op requires Random Access Iterator.

  2. The result of std::remove means "the new end of container". Logically, we should erase [ "the new end of container" , "the old end of container" ).

like image 70
ikh Avatar answered Nov 10 '22 19:11

ikh


It is equivalent for std::vector, but not for std::list or other containers. Not sure if subtracting iterators is even possible for std::list, and even if it is, it is a O(N) operation.

like image 29
green lantern Avatar answered Nov 10 '22 19:11

green lantern


It shouldn't make any difference; resize is defined in terms of insert and erase. But it is usually preferable to use the standard idiom, so that it can easily be recognized. And of course, the erase-remove idiom will work with any sequence container, and not just those which support resize. (All of the standard containers do seem to support resize, but it doesn't seem to be a requirement. So it might not be available on user defined containers, even though they support all required operations.)

In terms of performance: the resize must do one additional test, to determine whether it is erasing or inserting, but I can't imagine this making a significant impact.

like image 2
James Kanze Avatar answered Nov 10 '22 20:11

James Kanze


I think erase in erase(first,last) guarantees that no elements before first are accessed or modified, while resize only guarantees this when no reallocation happens because of the resize.

Edit: as pointed out by others, such a reallocation will never happen, so there's no difference

like image 1
Pieter Avatar answered Nov 10 '22 18:11

Pieter