0

我正在存储大量计算数据,并且我目前正在使用多态类型来减少所需的存储量。除了在我完成后删除对象之外,一切都非常快,我认为必须有更好的选择。代码计算每一步的状态,并根据存在的条件存储某些值。最坏的情况是存储完整的对象状态,最好的状态是几乎什么都不存储。(非常简化的)设置如下:

class BaseClass
{
public:
    virtual ~BaseClass() { }

double time;
    unsigned int section;
};

class VirtualSmall : public BaseClass
{
public:
    double values[2];
    int othervalue;
};

class VirtualBig : public BaseClass
{
public:
    double values[16];
    int othervalues[5];
};

...

std::vector<BaseClass*> results(10000);

在计算过程中会生成适当的对象类型,并将指向它的指针存储在向量中。vtable+pointer 的开销总体上远小于最大和最小对象之间的大小差异(根据 sizeof 至少为 200 字节)。由于通常可以使用最小的对象而不是最大的对象,并且可能存储了数千万个对象,因此可以节省几 GB 的内存使用量。然后可以非常快速地搜索结果,因为基类包含找到正确项目所需的信息,然后可以将其动态转换回它的真实类型。它在大多数情况下工作得很好。

唯一的问题是删除。当有数千万个对象时,释放所有内存需要几秒钟。删除代码遍历每个对象并delete results[i]调用虚拟析构函数。虽然解决问题并非不可能,但我认为必须有一个更优雅的解决方案。

这绝对可以通过分配较大的连续内存块(使用 malloc 或类似的)来完成,这些内存块被跟踪,然后生成一个正确的指针,指向块内的下一批空闲内存。然后将该指针存储在向量中。为了释放内存,需要对较少数量的大块调用 free()。没有更多的 vtable(它可以被更小的类型字段替换以确保正确的转换),这也节省了空间。虽然它是一个非常 C 风格的解决方案,但并不是特别漂亮。

对于我忽略的这类问题,是否有 C++ 风格的解决方案?

4

1 回答 1

1

您可以为您的类重载“new”运算符(即 void* VirtualSmall::operator new(size_t) ),并实现它们以从自定义分配器获取内存。我会为每个派生类使用一个块分配器,以便每个块大小是它应该存储的类的倍数。

当需要清理时,告诉每个分配器释放所有块。不会调用析构函数,因此请确保您不需要它们。

于 2013-07-18T23:45:34.637 回答