Reputation: 18219
Consider a code where we have a list of countries that contain a list of cities that contains a list of streets. Each City
in a given Country
contains exactly the same number of Street
s (nbStreetsPerCity
) and this number of streets per City
is constant over time.
class Street
{
};
class City
{
// Attribute
std::vector<Street> Streets;
// getter
Street& getStreet(int street_index) {return Streets[street_index];}
// More stuff
};
class Country
{
// Attribute
std::vector<City> Cities;
// getter
City& getCity(int city_index) {return Cities[city_index];}
// More stuff
};
I have to loop through each Street
and the process is quite fast when I have many Street
s and few City
ies but is quite slow when I have many City
ies with few Street
s
With such code, the Street
s of all City
ies of a given Country
are not contiguous in memory. For performance reasons, I would like to try a code with having all Street
s of a given Country
being contiguous in memory. I can't think of a way to have all the Street
s contiguous in memory without destroying part of the object oriented programming.
class Street
{
};
class Country
{
// Attribute
std::vector<Street> Streets;
int nbStreetsPerCity;
// getter
City getStreet(int city_index, int street_index)
{
Streets[city_index*nbStreetsPerCity + street_index]
};
// More stuff
};
With such code, all Street
s of a given country are contiguous in memory, however, I lost the City
object and therefore lost the advantage of OOP.
Is there a way to have all streets being contiguous in memory without loosing the advantage of OOP?
A very simple example would be very welcome!
Upvotes: 2
Views: 111
Reputation: 6993
The way to do this is to have a 'StreetManager' that contains your vector of streets. Your City and Country then contain references to the streets held by your street manager.
When I say 'references' these may be just indexes or some id or anything else that will allow lookup as per your read/write requirements.
By read/write requirements, I refer to the fact that references may be broken on vector edit, indexes will be broken on vector removal, and id will require a map of id -> index maintained by the manager.
The functions 'getStreets' in your City/country then just need to hand the indexes/ids to the manager and return the result.
The important thing to bear in mind is that attempting to edit the # of Streets in the manager will result in all the references being broken.
Upvotes: 2
Reputation: 15162
It can be done for the lowest level of such a fan-out but it would be a massive pain, for one thing you would have to know how many streets a city has before the allocation, and for another each street would have to be an equal sized object (meaning street names would have a maximum length).
You would replace the vector with a count and zero-sized array at the end of the city object, and instead of allocating with new you would have to use malloc or some other allocator and then use placement new to initialize the city into that buffer. You would then go through the list of steets and copy them into the array that actually exits after the city object.
Like I said, it can be done but is a pain. Make sure you actually have reason to do something like thins before going down such a path.
Upvotes: 0