Home > Mobile >  Frequently insert and delete elements using std::vector
Frequently insert and delete elements using std::vector

Time:08-13

I have a game which could have a million "boxes". For convenience, I use std::vector<shared_ptr<Boxes>> to save them. But today, I want to break some "box" if the box is subjected to a certain impact, so I have to split the box into "two small boxes".

Here is the question - in the game, there are so many "boxes" that would break which involves the std::vector insert (new small boxes generated) and delete (old boxes split). And each "box" contains many information like mass, shape, volume, and so on. So, I have no idea about enhancing performance of the std::vector for frequent inserts and deletes. And it is difficult for me to change to another data structure that I have to keep using std::vector.

I had read some efficient trick to use std::vector like: use reserve() before inserting elements to avoid reallocating memory, or maybe move semantic can be used here?

CodePudding user response:

Starting from an empty data structure:

std::vector<std::shared_ptr<Box>> boxes;

We can reserve capacity for 2 million boxes. This is probably too much, but allows for each box to be split once:

boxes.reserve(2_000_000);

Now, at the start of the game you can use push_back to fill up this vector.

At some later point, you decide you want to break a box in two. You can replace the original box with one of the fragments, and push_back the other one:

void breakBox(int i) {
  std::shared_ptr<Box> fragment1 = ...; // something that reads from boxes[i]
  std::shared_ptr<Box> fragment2 = ...; // something that reads from boxes[i]
  boxes[i] = fragment1;
  boxes.push_back(fragment2);
}

Simply adding boxes is still O(1) as long as you stay under the 2M boundary. Otherwise you incur a copy of the full boxes vector and then you are good for quite a while again.

Finally, should you ever want to remove a box, you can use a trick mentioned in the comments: swap it with the last box and then free the last box. This is O(1).

void deleteBox(int i) {
  std::swap(boxes[i], boxes.back());
  boxes.pop_back();
}
  • Related