我面临的问题是如何将封装和最佳内存使用结合起来。
我无法向您展示我的代码,因此可以在广泛的示例(我希望如此)上解释它。
假设我们需要一个男人的数据库。我们只想知道关于这些人的两件事:
管理这些数据的方便和自然的方法是创建一个对象,该对象对应于一个人,并将它们存储在一个数组中:
class OMan1 {
public:
OMan( const int &age, const astring &t ): fAge(age), fTown(t) {}
const int& age() const: { return fAge; }
const astring& Town() const: { return fTown; }
astring FullId() const: { return fTown+fAge; }
private:
int fAge;
astring fTown;
}
OMan mans[N];在这里,我们的OMans是自包含的对象,一切都很好。
除了我们克隆了数千次城镇的名字,这样浪费了内存和执行时间。
我们可以做的一个改进是为城镇名称和每个OMan存储创建独立的数组,只为城镇的年龄和一个指向城镇数组的指针:
class OMan2 {
// same functionality as for OMan1
int fAge;
int fTownId;
astring* fTowns;
}对象仍然是自给的,sizeof(int) + sizeof(void*)比sizeof(astring)小得多,我们赢得了很多。不过,这仍然是比规模(FAge)高出2-3倍的因素,而且我们重复了fTowns数十亿次。
内存优化对我来说是至关重要的,因此我所做的是只保留fAge和fTownId,并将像OMan ()和FullId()这样的功能从OMan类转移到某些类OManDataBase:
class OMan3 {
public:
OMan( const int &age, const int &tid ): fAge(age), fTownId(tid) {}
const int& age() const: { return fAge; }
const int& TownId() const: { return fId; }
// const astring& Town() const: { return fTown; }
// astring FullId() const: { return fTown+fAge; }
private:
int fAge;
int fTownId;
}
class OManDataBase {
// constructor, destructor
const int& age( const int& i) const: { return fMans[i].TownId()]; }
const astring& Town( const int& i) const: { return fTown[fMans[i].TownId()]; }
const astring& FullId( const int& i) const: { return Town(i)+age(i); }
private:
vector<OMan3> fMans;
vector<astring> fTowns;
}OMan3现在不是自带的对象。例如,它不知道它的全名。这意味着,如果我需要对一个人进行一些数据处理,我必须使用整个OManDataBase实例:
OBillType47 NewBillType47( const OManDataBase &db, int i ) { ... }而不是
OBillType47 NewBillType47( const OMan &m ) { ... }这里的封装已经中断,代码可读性明显降低。(我让Type47强调,我可以拥有许多函数,这些函数与阿曼-S一起工作,不能将它们全部包含在OManDataBase类中)。
我想知道是否有其他方法(-s)来解决数据复制问题,使对象尽可能地自我包含()。
发布于 2013-11-02 08:41:49
您可以创建这样的泛型类:
enum class Towns {T1 = 0, T2 = 1...}
string TownsNames[] = {"T1", "T2"...}
class OManDB
{
map<Towns, OMan*> m;
// OR
map<int, Towns> m; // map by Oman ID and town
public:
void addOMan();
Oman getOManById(int id);
OMan *getOManArrByTown(Towns town);
OMan getOManTown(int omanId);
...
}这样做的目的是创建一个类来保存所有记录,并为您执行所有操作,就像DB一样,您没有一个数据集和一组操作彼此分离。一切都在一个地方,您可以根据需要定义操作。
这样,您可以随意更改内部表示,您可以返回一个OMan数组--您基本上可以做任何您想做的事情,而不需要中断退出的代码。用户会知道他/她可以获得OMan,并且不需要知道存储它的字段的确切方法。您可以将它们存储在单个64位字段中(例如,如果ID只有32位,城镇是一个额外的32位字段)。它给了你自由。
更新
好,让我们暂时搁置封装,让我们来处理性能问题。理想情况下,对于每一点内存,您可以将ID和城镇的ID存储在两个不同的向量中,这将产生一个重要的优势,如果这两个字段的大小不同,并且编译器必须做一个填充。使用两个不同的数组将为您提供存储数据和避免填充的最佳选择(当然,您可以使用pack.但这是不可取的)
发布于 2013-11-19 15:06:29
对于这样一个问题,有一种特殊的设计模式:飞重模式。最好用它。
https://stackoverflow.com/questions/19740179
复制相似问题