考虑一个代码,其中我们有一个国家/地区列表,其中包含包含街道列表的城市列表。给定City
中的每个Country
包含完全相同数量的Street
s(nbStreetsPerCity
),并且每City
个街道的数量随时间不变。< / p>
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
};
我必须遍历每个Street
,当我有很多Street
和很少City
时这个过程非常快,但是当我有很多City
时,这个过程很慢几乎没有Street
s
使用此类代码,给定Street
的所有City
的{{1}}在内存中不连续。出于性能原因,我想尝试一个代码,其中给定Country
的所有Street
s在内存中是连续的。在没有破坏部分面向对象编程的情况下,我想不出让所有Country
连续存储的方法。
Street
使用这样的代码,给定国家/地区的所有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
};
在内存中是连续的,但是,我丢失了Street
对象,因此失去了OOP的优势。
有没有办法让所有街道在记忆中连续而不失去OOP的优势?
非常欢迎一个非常简单的例子!
答案 0 :(得分:2)
这样做的方法是拥有一个包含街道矢量的“StreetManager”。然后,您的城市和国家/地区包含街道管理员所持街道的引用。
当我说'引用'时,这些可能只是索引或某些id或其他任何允许根据您的读/写要求进行查找的内容。
通过读/写要求,我指的是在向量编辑时可能会破坏引用,在向量移除时会破坏索引,而id将需要id的映射 - &gt;由经理维护的指数。
您所在城市/国家/地区的函数'getStreets'只需将索引/ ID传递给经理并返回结果。
要记住的重要一点是,尝试编辑管理器中的Streets会导致所有引用被破坏。
答案 1 :(得分:0)
这可以用于这种扇出的最低级别,但这将是一个巨大的痛苦,有一件事你必须知道一个城市在分配之前有多少街道,而另一个街道将有另一个是一个大小相等的对象(意思是街道名称的最大长度)。
您将使用city对象末尾的count和zero-size数组替换向量,而不是使用new分配,您必须使用malloc或其他一些分配器,然后使用placement new将城市初始化为那个缓冲区。然后,您将浏览steets列表并将它们复制到实际在城市对象之后退出的数组中。
像我说的那样,它可以做到,但是很痛苦。在走这条路之前,确保你确实有理由做些类似的事情。