0

我将从上下文开始——我正在编写一个内存管理子系统,为此我提供了 new[]/delete[] 运算符的替代品。我必须解决的问题之一是如何存储由 new[] 分配的数组的大小,以便 delete[] 可以在解除分配的对象上调用析构函数。我选择的解决方案是分配更多内存并在实际数组的第一个元素之前存储数组的大小,然后返回指向该元素的指针。我想出了以下代码:

template<typename T, typename AllocatorType>
T* NewArrayHelper(size_t count, AllocatorType* allocator, const char* file, int line) {
    // Helper struct
    struct Helper {
        size_t Count;
        T Array[1];
    };

    Helper* ptr = allocator->Allocate(sizeof(Helper) + sizeof(T)*(count-1), ALIGNOF(Helper), file, line);

    // Call constructors, etc. ...

    return &ptr->Array[0];
}

我应该提一下,我喜欢这种方法的原因是编译器会计算出数组和 size_t 的正确对齐方式,除了读取它并传递给分配器(ALIGNOF 是一个宏)之外,我不需要做任何事情。此外,我不必做任何通过联合转换或转换为 char* hack,这些黑客必须解决别名等问题。

另一方面,现在我在替换 delete[] 运算符时遇到了问题。也就是说,它被交给了一个指向该结构内部的指针。

template<typename T, typename AllocatorType>
void DeleteArrayHelper(T* ptr, AllocatorType* allocator, const char* file, int line) {
    // Helper struct
    struct Helper {
        size_t Count;
        T Array[1];
    };

    // Here ptr points to Array[0] in Helper struct
}

如何以最少的黑客攻击并且可能可移植的方式将这样的指针转换为指向整个结构的指针?

4

1 回答 1

0

像这样的东西会起作用,并且应该是可移植的:

Helper *h = (Helper*)((uintptr_t)ptr - offsetof(Helper, Array[0]));

uintptr_t通常在stdint.h.

于 2012-04-20T04:08:48.803 回答