0%

Allocator in C++

Allocator for C++11

滿足C++11中對Alloocator的需求,所能寫出的最簡單allocator
注意

  • 這邊的allocatte和deallocate不會呼叫Constructor/Destructor,只是單純的記憶體分配,為了簡單,直接用malloc/free
  • 可以對兩個Allocator做比較的動作,如果兩者相等的話,可以達成在A進行allocate,而在B進行deallocate的動作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <cstdlib>

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

T* allocate(size_t num) { return allocate(num, nullptr); }
T* allocate(size_t num, const void* hint) { return reinterpret_cast<T*>(std::malloc(sizeof(T) * num)); }
void deallocate(T* ptr, size_t num) { std::free(ptr); }
Minallocator() = default;
~Minallocator() = default;
Minallocator(const Minallocator&) = default;
Minallocator(Minallocator&&) = default;
Minallocator& operator=(const Minallocator&) = default;
Minallocator& operator=(Minallocator&&) = default;
};

template <typename T1, typename T2>
bool operator==(const Minallocator<T1>& lhs,const Minallocator<T2>& rhs)
{
return true;
}

template <typename T1, typename T2>
bool operator!=(const Minallocator<T1>& lhs, const Minallocator<T2>& rhs)
{
return false;
}

而要用自己的Allocate就可以這麼做

1
std::vector<int, Minallocator<int>> v;

std::scoped_allocator_adaptor

不常用,有用到再說

rebind

已知T類型的Allocator,想要根據相同策略拿到U類型的Allocator
也就是說希望用同樣的方式來分配U
可以透過

1
allocator<U>=allocator<T>::rebind<U>::other.

拿到,因此

std::allcoator<T>::rebind<U>::other等同於std::allcoator<U>
Myallcoator<T>::rebind<U>::other等同於Myallcoator<U>

在libstdc++中的實現

1
2
3
4
5
template <typename _Tp1>
struct rebind
{
typedef allocator<_Tp1> other;
};

Problem with allocators and containers

這樣的程式碼會有問題

1
2
3
4
ector<int, Minallocator<int>>  pool_vec  { 1, 2, 3, 4 };
vector<int, Other_allocator<int>> other_vec { };

other_vec = pool_vec;    // ERROR!

因為兩者的Allocator Type不同,所以直接複製不行,所以只要兩者相同就行了,也就是C++17 PMR的初衷

C++17 Polymorphic Memory Resource

新提出來的memory_resource是個asbtract class,不同的instance會有不同的行為
因此可以可以這樣做

1
2
3
4
5
6
7
8
9
10
11
12
13
// define allocation behaviour via a custom "memory_resource"
class my_memory_resource : public std::pmr::memory_resource { ... };
my_memory_resource mem_res;
auto my_vector = std::pmr::vector<int>(0, &mem_res);

// define a second memory resource
class other_memory_resource : public std::pmr::memory_resource { ... };
other_memory_resource mem_res_other;
auto my_other_vector = std::pmr::vector<int>(0, &mes_res_other);

auto vec = my_vector; // type is std::pmr::vector<int>
vec = my_other_vector; // this is ok -
// my_vector and my_other_vector have same type

Reference