简体   繁体   中英

How to move all the pointers from one vector to another?

Basically what I want to do is remove some of the pointers inside my vector, but I found out that it can be quite slow to do that in the middle of the vector.

So I have a vector that already has data inside:

std::vector<Class*> vec1; // This already contains pointers

I'll iterate through vec1 and will add some of the pointers to another vector (vec2): vec2.push_back(vec1.at(index))

Now I would like to do is something like vec1 = vec2 but I don't know if this is the better (effecient) way to do that.

What would be the best way to do that?

I tried:

  1. While looping through vec1 simply erasing what I need to remove from it:

    it = vec1.erase(it)

  2. While looping through vec1 moving the last item to the actual index and poping_back

    vec1.at(index) = vec1.back(); vec1.pop_back();

  3. Setting some attribute on the object the pointer is pointing while looping through vec1 and than using std::remove_if

    vec1.erase(std::remove_if(vec1.begin(), vec1.end(), shouldBeRemoved), vec1.end());

  4. Now I'm trying to generate a new vector while looping through vec1 and adding the pointers I want to keep, then "swapping" or "moving" the contents of this new vector to vec1.

Apparently when doing it the 4th way, the pointers get invalidated :(

I would love to see what you guys suggest me. A big thank you to everyone that is willing to help!

You can just use std::remove_if to conditionally remove items from a vector. This algorithm will shift items that need to be kept over to the front. Follow it up with a std::vector::erase call to actually remove the items not shifted to the front.

This is similar to your option 3, but you don't need to set an attribute first - just use a predicate that determines if the item should be kept or not, and avoid having to pass over the vector twice.

If you don't want to do it in-place, but want to fill a new vector, then std::copy_if does that.

Removing things from a vector should be done with the erase remove idiom

It is well covered here: https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom

The basic idea is to shift the elements first and then erase the unneeded items which is faster than erasing and shifting each individual element which is done as from the example with:

v.erase( std::remove( v.begin(), v.end(), 5 ), v.end() );

But in general: If you have a lot of add/erase steps in your algorithm, you should use a std::list where removing elements in the middle is much cheaper at all.

Your attempt #2 suggests that you're not interested in the order of the elements. remove_if will suffer performance problems as it will maintain the order of the items that you don't delete; meaning you could do a substantial number of shifts to maintain this order.

The swapping and popping will suffer the problem that repeatedly popping the back isn't required - it could resize the vector or do other things.

As such, by combining the ideas - of swapping the "last not swapped out" (ie last the first time, 2nd last the 2nd etc) and then at the end erasing the end items once complete; you should have the fastest algorithm.

Some of the comments suggest that a copy is faster than a swap; and while true when doing a single copy; for a vector when you're copying multiple elements multiple times; the swap will be significantly faster.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM