简体   繁体   English

为 std::unordered_map 创建一个惯用的基于堆栈的分配器

[英]Creating an idiomatic stack based allocator for std::unordered_map

I'm writing a custom allocator for unordered_map to allocate on the stack.我正在为 unordered_map 编写一个自定义分配器以在堆栈上分配。 I'm a bit lost on how to do this idiomatically: Should I pass the stack resource as pointer to the allocator or even define the byte array inside the allocator?我对如何惯用地执行此操作有点迷失:我应该将堆栈资源作为指针传递给分配器,还是在分配器内定义字节数组? What is common practice here?这里的常见做法是什么?

#include <memory>
#include <unordered_map>
#include <utility>
#include <limits>
#include <cstdio>
#include <string_view>
#include <array>

class some_stack_resource
{
    std::array<std::byte, 100> container_; // <-- how to allocate to this?
};

template <typename T>
class custom_allocator
{
public:
    using value_type = T;

    using pointer = T*;
    using const_pointer = const T*;

    using void_pointer = void*;
    using const_void_pointer = const void*;

    using size_type = size_t;
    using difference_type = std::ptrdiff_t;

    template <typename U>
    struct rebind
    {
        using other = custom_allocator<U>;
    };

    custom_allocator() noexcept {
        printf("Default constructed\n");
    }

    template <typename U>
    custom_allocator(const custom_allocator<U>& other) noexcept {
        printf("Copy constructed\n");

    }

    ~custom_allocator() {
        printf("Destructed\n");
    }

    pointer allocate(size_type numObjects, const_void_pointer hint) {
        return allocate(numObjects);
    }

    pointer allocate(size_type numObjects) {
        printf("allocate %zu\n", numObjects);
        return static_cast<pointer>(operator new(sizeof(T) * numObjects));
    }

    void deallocate(pointer p, size_type numObjects) {
        printf("deallocate %zu\n", numObjects);
        operator delete(p);
    }

    size_type max_size() const {
        return std::numeric_limits<size_type>::max();
    }

    template<typename U, typename... Args>
    void construct(U* p, Args&&... args) {
        new(p) U(std::forward<Args>(args)...);
    }

    template <typename U>
    void destroy(U *p) {
        p->~U();
    }
};

int main()
{
    some_stack_resource res; // <-- where to pass res idiomatically?

    using Key = std::string_view;
    using T = int;
    std::unordered_map<Key, T, std::hash<Key>, std::equal_to<Key>, custom_allocator<std::pair<const Key, T>>> m{ {"hello", 2} };
}

here is a good example of a short allocator Hinnant's short_alloc and based on it you can see how to 'hide' some_stack_resource inside custom_allocator from users.这是一个简短的分配器Hinnant 的 short_alloc的一个很好的例子,基于它你可以看到如何在custom_allocator中“隐藏” some_stack_resource对用户。 As a user of your code I wont create an extra entity some_stack_resource res;作为您代码的用户,我不会创建额外的实体some_stack_resource res; because it doesn't make code clean.因为它不会使代码干净。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM