[英]Custom allocator for nested containers
我正在研究自定義分配器。 到目前為止,我已經嘗試使用簡單的容器:std::list、std::vector、std::basic_string 等...
我的自定義分配器是一個 static 緩沖區分配器,它的實現很簡單:
#include <memory>
template <typename T>
class StaticBufferAlloc : std::allocator<T>
{
private:
T *memory_ptr;
std::size_t memory_size;
public:
typedef std::size_t size_type;
typedef T *pointer;
typedef T value_type;
StaticBufferAlloc(T *memory_ptr, size_type memory_size) : memory_ptr(memory_ptr), memory_size(memory_size) {}
StaticBufferAlloc(const StaticBufferAlloc &other) throw() : memory_ptr(other.memory_ptr), memory_size(other.memory_size){};
pointer allocate(size_type n, const void *hint = 0) { return memory_ptr; } // when allocate return the buffer
void deallocate(T *ptr, size_type n) {} // empty cause the deallocation is buffer creator's responsability
size_type max_size() const { return memory_size; }
};
我以這種方式使用它:
using inner = std::vector<int, StaticBufferAlloc<int>>;
int buffer[201];
auto alloc1 = StaticBufferAlloc<int>(&buffer[100], 50);
inner v1(0, alloc1);
assert(v1.size() == 0);
const int N = 10;
// insert 10 integers
for (size_t i = 0; i < N; i++) {
v1.push_back(i);
}
assert(v1.size() == N);
到目前為止一切都很好,當我增加 N 超過它拋出的最大緩沖區大小時,這是預期的。
現在,我正在嘗試使用嵌套容器。 簡而言之,我試圖擁有一個向量(矩陣)的向量,其中父向量及其所有底層元素(即向量,即容器)共享相同的 static 分配緩沖區。 看起來scoped_allocator可以解決我的問題。
using inner = std::vector<int, StaticBufferAlloc<int>>;
using outer = std::vector<inner, std::scoped_allocator_adaptor<StaticBufferAlloc<inner>>>;
int buffer[201];
auto alloc1 = StaticBufferAlloc<int>(&buffer[100], 50);
auto alloc2 = StaticBufferAlloc<int>(&buffer[150], 50);
inner v1(0, alloc1);
inner v2(0, alloc2);
assert(v1.size() == 0);
assert(v2.size() == 0);
const int N = 10;
// insert 10 integers
for (size_t i = 0; i < N; i++)
{
v1.push_back(i);
v2.push_back(i);
}
assert(v1.size() == N);
assert(v2.size() == N);
outer v // <- how to construct this vector with the outer buffer?
v.push_back(v1);
v.push_back(v2);
...
我的問題是如何使用其 static 緩沖區在其構造函數調用中初始化外部向量?
在 C++11/C++14 中創建作用域分配器有點挑戰。 所以我選擇了 C++17 中介紹的一個非常現代的解決方案。我沒有實現分配器,而是使用了polymorphic_allocator 。 多態分配器是作用域分配器,標准容器會自動將分配器傳遞給子對象。
基本上,這個想法是使用多態分配器並將其注入monotonic_buffer_resource 。 monotonic_buffer_resource 可以用memory 資源初始化。
編寫自定義 memory 資源非常簡單:
class custom_resource : public std::pmr::memory_resource
{
public:
explicit custom_resource(std::pmr::memory_resource *up = std::pmr::get_default_resource())
: _upstream{up}
{
}
void *do_allocate(size_t bytes, size_t alignment) override
{
return _upstream; //do nothing, don't grow just return ptr
}
void do_deallocate(void *ptr, size_t bytes, size_t alignment) override
{
//do nothing, don't deallocate
}
bool do_is_equal(const std::pmr::memory_resource &other) const noexcept override
{
return this == &other;
}
private:
std::pmr::memory_resource *_upstream;
};
使用它更簡單:
std::byte buffer[512];
custom_resource resource;
std::pmr::monotonic_buffer_resource pool{std::data(buffer), std::size(buffer), &resource};
std::pmr::vector<std::pmr::vector<int>> outer(&pool)
重要的是要注意std::pmr::vector<T>
只是std::vector<T, polymorphic_allocator>
。
有用的資源:
std::pmr 很酷,但它需要 gcc 的現代版本才能運行 (9+)。 幸運的是,Reddit 上到處都是善良的陌生人。 可以在此處找到 C++14 解決方案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.