c++ - C++ 17和更新的std::allocators是否可用于动态数量的自定义堆?

标签 c++ c++17

这是我的情况:

有一组Instance对象,这些对象的数量在运行时确定。

对于每个实例,都会创建一个自定义堆。 (是的,我指的是::HeapCreate()等所有win32函数)。

struct Instance
{
   HANDLE heap;
};

现在,有一些特定于Instance的State对象,该对象可以访问(实例)实例。它是1:1的关系。每个实例1个状态。
struct State
{
    Instance * inst;

};

在那种状态下,我想使用std::vector之类的STL容器,但是我希望那些容器使用分配器,该分配器使用实例创建的堆。

阅读从C++ 98到C++ 17以及更高版本的std::allocator的历史,已经删除了一些旧的要求,但是我的收获是,不可能为我的上面编写这样的分配器显示的用例。假设分配器每次都具有相同的类型,但是是有状态的(例如在使用不同堆HANDLE的实例中)。

所以这是我的问题:
  • 我可以还是应该在这个用例中尝试使用STL分配器,还是最好只滚动我自己选择的几个自己的容器类?
  • 我偶然发现了std::pmr C++ 17命名空间,想知道那里是否有我不熟悉的东西,这将对我的用例有所帮助。

  • 如果您以现代方式(C++ 17和更高版本)展示如何解决此问题的“惯用方式”,您的答案将非常有值(value)。

    在这里,我不完整和当前的“正在进行中的工作”。随着时间的推移,我将根据答案和评论以及我自己的进度填写更多内容。
    #include <Windows.h>
    
    struct custom_heap_allocator
    {
        HANDLE heap;
    
        // No default constructor
        custom_heap_allocator() = delete;
    
        // an instance is tied to a heap handle.
        explicit custom_heap_allocator(HANDLE h)
            : heap{ h }
        {
    
        }
    
        // can I get away with this....
    
        // copy constructor for same type.
        custom_heap_allocator(const custom_heap_allocator& other)
            : heap{ other.heap }
        {
    
        }
    
        //... or do I need something like this? Or is it somehow covered by rebind?
        //template<class U>
        //custom_heap_allocator(const custom_heap_allocator<U>& other)
        //  : heap{ other.heap }
        //{
    
        //}
    
        template<class U>
        struct rebind {
            typedef custom_heap_allocator other;
        };
    };
    
    template <class T, class U>
    constexpr bool operator== (const custom_heap_allocator& a1, const custom_heap_allocator& a2) noexcept
    {
        return a1.heap == a2.heap;
    }
    
    template <class T, class U>
    constexpr bool operator!= (const custom_heap_allocator& a1, const custom_heap_allocator& a2) noexcept
    {
        return a1.heap != a2.heap;
    }
    

    注意:关闭Instance只会破坏堆(不需要为仍在堆上的东西调用析构函数,因为这些只是简单的数据,而不是系统资源,等等。它们持有的所有动态东西也来自同一堆实例)。

    最佳答案

    这是您(已编辑)问题中分配器的更完整版本。

    cpp.sh/4viaj上使用std::vector和std::list的一些基本单元测试

    template<typename T>
    struct custom_heap_allocator
    {
        using value_type = T;
        using pointer = T*;
        using const_pointer = const T*;
        using reference = T&;
        using const_reference = const T&;
    
        // No default constructor
        custom_heap_allocator() = delete;
    
        // An instance is tied to a heap handle.
        explicit custom_heap_allocator(HANDLE h)
            : heap{ h }
        {
        }
    
        // Instances are copy-constructable and copy-assignable.
        custom_heap_allocator(const custom_heap_allocator&) = default;
        custom_heap_allocator& operator=(const custom_heap_allocator&) = default;
    
        // All related allocators share the same heap, regardless of type.
        template<class U>
        custom_heap_allocator(const custom_heap_allocator<U>& other)
          : heap{ other.heap }
        {
        }
    
        // Allocate and deallocate space for objects using the heap.
        T* allocate(size_t n) {
            return static_cast<T*>(HeapAlloc(heap, 0, sizeof(T) * n)); 
        }
        void deallocate(T* ptr, size_t n) {
            HeapFree(heap, 0, ptr);
        }
    
        // Construct and destroy objects in previously allocated space.
        // This *should* be optional and provided by std::allocator_traits,
        // but it looks like some std containers don't use the traits.
        template< class U, class... Args >
        void construct( U* p, Args&&... args ) {
            ::new((void *)p) U(std::forward<Args>(args)...);
        }
        template< class U >
        void destroy( U* p ) {
            p->~U();
        }
    
        // Template for related allocators of different types.
        template<class U>
        struct rebind {
            typedef custom_heap_allocator<U> other;
        };
    
    private:
        // Heap used for all allocations/deallocations.
        HANDLE heap;
    
        // Allow all related types to access our private heap.
        template<typename> friend struct custom_heap_allocator;
    };
    

    关于c++ - C++ 17和更新的std::allocators是否可用于动态数量的自定义堆?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59464077/

    相关文章:

    c++ - 如何限制QtCharts的缩放?

    c++ - 什么是 "allocation context"?

    c++ - 优化读写大数据(C++)

    c++ - 有没有办法使用十进制 ASCII 码通过自动类型推断来获取字符?

    c++ - 推导出具有默认模板参数的模板函数指针的模板参数

    c++ - 如何将 QEvents 传递给子部件?

    c++ - 预先为 C++ 应用程序分配内存

    c++17倍表达式语法

    c++ - 如何检测构造函数是否真的是 constexpr,以便我可以使用静态初始化?

    C++ 转换运算符到 chrono::duration - 适用于 c++17 但不适用于 C++14 或更低版本