Search code examples
c++performancevectorpush-back

How can I avoid extra copying when constructing a vector to be returned?


C++ newbie here! I wrote a code who is considering a WORLD which made of a vector of CITIES. This world gets updated nbTimeStep times. Here is a rough summary of what my code looks like. For ease of reading, all class names are in all caps.

// Definition of Class `WORLD`
class WORLD
{
  private:
    vector<CITY> cities;
  public:
    void AddCity(CITY& city)
    {
      cities.push_back(city);
    }
}

// In main

WORLD world(Arguments);
for (int time_step=0 ; time_step < nbTimeSteps ; time_step++)
{
   WORLD EmptyWorld;
   world = ReCreateWorld(world,EmptyWorld); // The object `EmptyWorld` will be returned after being 'filled' with cities.
}

where the function ReCreateWorld is defined as

WORLD& ReCreateWorld(WORLD& OldWorld, WORLD& NewWorld)
{
  for (int city_index=0 ; city_index < NbCities ; city_index++)
  {
    /* Long Process of creating a single 'CITY' called `city`
    ...
    ...
    */


    // Add the city to the list of cities (process I am trying to optimize)
    NewWorld.AddCity(city);
  }
    return NewWorld;
}

After profiling, I see that about 20% of the time the process is in the method AddCity. I never need two instances of any given CITY, so it seems silly to lose so much time copying each city. How could I go around this issue?


Some may want to comment on the fact that I pass an empty WORLD to ReCreateCities as it is not very elegant. I did that mainly to emphasize that the slow copying part happen at the line cities.push_back(city); and not when ReCreateWorld return its WORLD.


Solution

  • Like Justin and Daniel suggested, use a move c-tor. Old school way is to use pointers, e.g. typedef std::unique_ptr CITY_PTR; std::vector cities; And push only pointers of cities.

    You can try something similar to emplace http://www.cplusplus.com/reference/vector/vector/emplace/ which forwards c-tor arguments directly.