10

The "normal" way of deleting an element from a vector goes like this:

vec.erase(vec.begin() + index);

But in theory it's faster just to do this:

if (vec.size() > 1)
{
    std::iter_swap(vec.begin() + index, vec.end() - 1);
    vec.pop_back();
}
else
{
    vec.clear();
}

Is there any reason to not use the latter?

user112513312
  • 459
  • 1
  • 7
  • 15
  • 5
    You need the normal way if you need to preserve order. – zch Jan 25 '16 at 13:55
  • 1
    If you need deletion to be fast, you can always consider using a linked list. – CompuChip Jan 25 '16 at 14:11
  • 10
    @CompuChip That'll end up slower than the second example, though, and linked lists are basically slow-by-default. – Veedrac Jan 25 '16 at 15:11
  • 3
    @CompuChip But linked lists have numerous problems of their own. The biggest issue is the cost associated with traversing the nodes, which can result is several cache misses (or even worse, segfaults) along the way. – user112513312 Jan 25 '16 at 15:35
  • @user112513312 true, just pointing out that if you _really_ need a data structure with guaranteed constant-time complexity, it exists. I agree that in general (i.e. before measuring performance and figuring out that the moves resulting from deleting from a vector are the bottleneck), `vector` is the most sensible default. – CompuChip Jan 25 '16 at 21:27
  • 1
    I know this is an old question but its worth saying: Swap and pop is a great way to give a nice performance uptick to unordered vectors. Especially for large vectors when random access is needed. Just keep in mind that changes to the container can invalidate iterators and pointers. – pmw1234 Nov 23 '22 at 14:45

1 Answers1

17

The second case does not preserve the order of the elements in the vector. If this is a sorted vector or the order is important then you have just broken that in the second case where the first case would leave the order intact.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • 2
    And if the order is not important then a vector was probably not the right tool for whatever the job is. Though there are some cases where order is _so_ unimportant that a vector is the right tool the job :D – Lightness Races in Orbit Jan 25 '16 at 14:34
  • 1
    @LightnessRacesinOrbit `vector` is a reasonable tool when "order of insertion" is the operative ordering, rather "ordered by property" – Caleth Oct 08 '18 at 08:22
  • @Caleth Agreed, but then you still have a desired order ;) – Lightness Races in Orbit Oct 08 '18 at 10:00
  • 1
    @LightnessRacesinOrbit no you don't, the most recently inserted element is now somewhere in the middle of the container – Caleth Oct 08 '18 at 11:19
  • @Caleth The most recently inserted element is exactly where you put it, presumably deliberately and for some reason. I don't really follow what you're saying? – Lightness Races in Orbit Oct 08 '18 at 11:23
  • @LightnessRacesinOrbit `std::vector v; v.push_back(1); v.push_back(2); v.push_back(3); v.push_back(4); fake_erase(v, 1);` Now `v` is { 1, 4, 3 }, not { 1, 3, 4 } – Caleth Oct 08 '18 at 11:29
  • @Caleth: What is `fake_erase`? Sorry, I really don't know what point you're trying to make, or how it relates to this answer/my comment. – Lightness Races in Orbit Oct 08 '18 at 12:37
  • @LightnessRacesinOrbit A method wrapping OP's `iter_swap + pop_back`. The insertion order of those elements is 1, 2, 3, 4. After removing the second element (2), the order is then 1, 4, 3. This has not preserved the order of insertion, which would be 1, 3, 4 – Caleth Oct 08 '18 at 12:38
  • @LightnessRacesinOrbit I believe `fake_erase` is the erase the OP is proposing. Caleth is saying if the vector of `{1,2,3,4}` is passed to that and `2` is erased then you'd get back `{1,4,3}` which does not preserve the "order of insertion" – NathanOliver Oct 08 '18 at 12:39
  • @NathanOliver Then I'm confused as to what part of my original comment is being disagreed with! – Lightness Races in Orbit Oct 08 '18 at 13:29
  • @LightnessRacesinOrbit Me too. I guess they were just pointing out that if you need the order of insertion then vector is the right tool for the job, which doesn't disagree with your original comment at all. – NathanOliver Oct 08 '18 at 13:33
  • 1
    @LightnessRacesinOrbit Eh? What is the difference between 'not important' and 'so unimportant'? If I just iterate elements of a vector and don't care about the order, vector is _the_ right tool for the job. – Hedede Oct 09 '21 at 15:24