自定义内存分配和删除

时间:2014-08-28 15:10:09

标签: c++

struct Rational
{
    int a;
    int b;
};

struct NextOnFreeList
{
    NextOnFreeList *next;
};

// Build the linked-list
NextOnFreeList* freeList = NULL; // head of the linked-list
size_t size = (sizeof(Rational) > sizeof(NextOnFreeList *)) ? sizeof(Rational) : sizeof(NextOnFreeList *);
NextOnFreeList *runner = static_cast <NextOnFreeList *> new char [size]; // LineA
freeList = runner;
for (int i = 0; i < EXPANSION_SIZE; i++) {
    runner->next = static_cast <NextOnFreeList *> new char [size];
    runner = runner->next;
}
runner->next = 0;

问题1&gt; LINEA 由于Rational的大小(即8字节)大于NextOnFreeList(即4字节), Linked-list中的每个元素只使用部分已分配的内存。这是对的吗?

// Delete the linked-list

NextOnFreeList *nextPtr = NULL;
for (nextPtr = freeList; nextPtr != NULL; nextPtr = freeList) {
    freeList = freeList->next;
    delete [] nextPtr; // LineB
}

问题2&gt; LineB 我们为什么要使用'delete [] nextPtr'而不是'delete nextPtr'?

问题3&gt;

Rational* ptr = static_cast<Rational*>( freeList ); // LineC
ptr->a = 10;
ptr->b = 20;

LineC是否属实,我们可以带回原始大小为'size'的所有已分配内存 使用内存来存储Rational中的所有元素。

3 个答案:

答案 0 :(得分:2)

Q1:是的,但我宁愿使用std::allocator<Rational>::allocate(或两者的union - 你会以这种方式避免对齐问题)

Q2:这实际上很糟糕,因为您应先将其转换为char*,然后再使用delete[]。再次,使用std::allocator会更好。 :默认实施无关紧要(调用free),但忘了我说的那样;)...直接使用malloc / free更安全

Q3 ::没关系,但我不确定static_cast是否会允许reinterpret_cast或者void*之间的malloc可以提供帮助)

编辑:我希望你的 Q3 不是最终的,因为你需要先更新空闲列表(在使用指针之前)。

第二次编辑:链接+注意:隐藏分配器内的空闲列表最适合C ++(直接使用free / new[]或{{ 1}} / delete[]

答案 1 :(得分:0)

<强> Q.1:

是的,但这不是使用static_cast的最佳选择。 reinterpret_cast会更优选。

<强> Q.2: 我没有定义的行为来识别您的static_cast接受简单的delete。最安全的方法是将此视为数组的原始分配。所以请回到char*并使用[]delete

Q.3 是的,是的,你可以。

答案 2 :(得分:0)

  1. 这似乎是正确的。在32位架构中,您最有可能进行过度分配,并且只使用一部分内存。在64位架构中,最有可能两种尺寸相同。
  2. 两者都不合适。您已将该内存分配为char*,因此您必须将其删除(通过转回char*然后delete[])或您有未定义的行为。
  3. C行无法编译,因为两个指针类型不相关。如果您 使用reinterpret_cast,则会违反严格的别名规则,再次导致未定义的行为。