是否可以使用自定义分配器来分配任意大小的区域?

Is it possible to use a custom allocator to allocate an arbitrary sized area?

我有一个容器 class 管理不同块中的底层内存。块的数量随容器中存储的对象数量而变化。每当容器即将超过当前可用内存时,我都会分配一块新的内存。而且,只要不再使用,就释放一个块。因此,数字块在运行时是可变的。因此,我必须将块指针存储在动态 growing/shrinking 数组中。

/*** Container Class ***/
template<class T, class Allocator = std::allocator<T>>
class CustomContainer{
public:    
    // Some member methods here..

private:
    void createNewChunk()
    {
        // Some code goes here ...

        newChunkAddr = new T*[CHUNK_SIZE];
    }

    void destroyChunk(T* chunkAddr)
    {
         // Some code goes here ...

         delete [] chunkAddr;
    }    

private:
    /*** Members ***/
    // Some other members ...
    std::size_t size        = 0;
    T**         chunks      = nullptr;
    Allocator   allocator;
};

只要使用此容器的系统有堆,一切都很好,因此可以正确实现 operator new。当系统不使用 operator new 并且用户假定容器将使用它提供的 Allocator 分配任何动态资源时会出现问题。

经过快速的头脑风暴,我立即想到可以使用 std::allocator_traits class 的 allocate method 来分配所需的 space。不幸的是,该方法只能分配大小恰好是分配器中使用的模板值类型倍数的区域。下面是对应函数的解释:

Uses the allocator a to allocate n*sizeof(Alloc::value_type) bytes of uninitialized storage. An array of type Alloc::value_type[n] is created in the storage, but none of its elements are constructed.

问题来了,allocating/deallocating space 存储块指针的正确方法是什么?

what is the proper way of allocating/deallocating the space for storing the chunk pointers?

任何分配内存的正确方法都是正确的方法。每个都有其优点和缺点。您应该根据哪些优点和缺点对您的用例很重要来进行选择。

如果您希望避免动态存储,您可以使用静态存储,但这会限制您的最大块数。或者如果你不介意动态存储,那么你可以使用全局分配器。

您甚至可以通过提供单独的自定义分配器让用户自定义该分配。

标准容器的方式——这也是一种正确的方式,但不是唯一正确的方式——是它们会创建一个类型为 std::allocator_traits<Allocator>::rebind_alloc<T*> 的新分配器。如果您确实采用了使用单独的自定义分配器的方式,那么这将是第二个分配器的合理默认值。

I've to store the chunk pointers in a dynamically growing/shrinking array.

标准库中有一个用于该目的的容器:std::vector。您可以在您的容器中使用它。


P.S。您对容器的描述与 std::deque 非常相似。考虑使用它是否会更简单。