一个 vector 可以容纳两个分配器或使用不同的分配器来分配和构造/销毁吗?

问题描述 投票:0回答:1

我正在尝试实现我的自定义向量。在某些情况下,我决定将容量放在真实数据的前面,通过移动指针来访问容量。 假设

sizeof(capacity) == 4
sizeof(value_type) == 512
,使用
allocator<T>
无疑会造成内存碎片,这可能是不可接受的。 因此,我不能使用
allocator<T>::allocate
来分配整个块内存。 但是,我可以同时持有两个分配器(
allocator<T>
rebind_alloc<byte>
),然后通过
rebind_alloc<byte>
分配内存并通过
allocator<T>
构造值。我不知道它是否符合标准要求。或者,还有什么好主意吗?

c++ vector allocator
1个回答
0
投票

为一个容器保留两个分配器可能很难维护,所以根据我的问题,我需要的是一个状态分配器。 标准库中已经有了现成的范式,叫做

std::scoped_allocator_adapater
.

std::scoped_allocator_adaptor
类模板是一个分配器,可用于多级容器(地图元组列表列表的向量等)。它使用一个外部分配器类型
OuterAlloc
和零个或多个内部分配器类型
InnerAlloc...
进行实例化。直接用
scoped_allocator_adaptor
构造的容器使用
OuterAlloc
分配其元素,但如果元素本身是容器,则它使用第一个内部分配器。该容器的元素,如果它们本身是容器,则使用第二个内部分配器等。如果容器的级别多于内部分配器,则最后一个内部分配器将重新用于所有进一步嵌套的容器。

那个

std::scoped_allocator_adapter
是我这里需要的。所以,我这样实现我的分配器:

template <class AllocByte, class AllocTy>
class MyAlloc : AllocTy, AllocByte {
    using alty_traits   = std::allocator_traits<AllocTy>;
    using albyte_traits = std::allocator_traits<AllocByte>;

public:
    using alty_type   = AllocTy;
    using albyte_type = AllocByte;

    // other functions and type alias

    albyte_type& byte_allocator() noexcept { return static_cast<AllocByte&>(*this); }

    const albyte_type& byte_allocator() const noexcept { return static_cast<const AllocByte&>(*this); }

    alty_type& value_allocator() noexcept { return static_cast<AllocTy&>(*this); }

    const alty_type& value_allocator() const noexcept { return static_cast<const AllocTy&>(*this); }

    pointer allocate(size_type n) { return albyte_traits::allocate(byte_allocator(), n); }

    void deallocate(pointer ptr, size_type n) { return albyte_traits::deallocate(byte_allocator(), ptr, n); }

    size_type max_size() const { return albyte_traits::max_size(byte_allocator()); }

    template <class _Ty, class... _Args>
    void construct(_Ty* ptr, _Args&&... args) {
        alty_traits::construct(value_allocator(), ptr, std::forward<_Args>(args)...);
    }

    template <class _Ty>
    void destroy(_Ty* ptr) {
        alty_traits::destroy(value_allocator(), ptr);
    }
};
© www.soinside.com 2019 - 2024. All rights reserved.