Skip to content

Instantly share code, notes, and snippets.

@seaside2mm
Last active November 5, 2022 00:28
Show Gist options
  • Save seaside2mm/8f63e26ef036551c3c064d17ebd65107 to your computer and use it in GitHub Desktop.
Save seaside2mm/8f63e26ef036551c3c064d17ebd65107 to your computer and use it in GitHub Desktop.
[allocator] #cpp
#include <cstdlib>
#include <new>
#include <limits>
#include <iostream>
#include <vector>
template <class T>
struct Mallocator
{
typedef T value_type;
Mallocator () = default;
template <class U> constexpr Mallocator (const Mallocator <U>&) noexcept {}
[[nodiscard]] T* allocate(std::size_t n) {
if (n > std::numeric_limits<std::size_t>::max() / sizeof(T))
throw std::bad_array_new_length();
if (auto p = static_cast<T*>(std::malloc(n*sizeof(T)))) {
report(p, n);
return p;
}
throw std::bad_alloc();
}
void deallocate(T* p, std::size_t n) noexcept {
report(p, n, 0);
std::free(p);
}
private:
void report(T* p, std::size_t n, bool alloc = true) const {
std::cout << (alloc ? "Alloc: " : "Dealloc: ") << sizeof(T)*n
<< " bytes at " << std::hex << std::showbase
<< reinterpret_cast<void*>(p) << std::dec << '\n';
}
};
template <class T, class U>
bool operator==(const Mallocator <T>&, const Mallocator <U>&) { return true; }
template <class T, class U>
bool operator!=(const Mallocator <T>&, const Mallocator <U>&) { return false; }
int main()
{
std::vector<int, Mallocator<int>> v(8);
v.push_back(42);
}
#include <list>
#include <memory>
#include <chrono>
#include <iostream>
#ifdef __GNUC__
#include <ext/array_allocator.h>
#include <ext/mt_allocator.h>
#include <ext/debug_allocator.h>
#include <ext/pool_allocator.h>
#include <ext/bitmap_allocator.h>
#include <ext/malloc_allocator.h>
#include <ext/new_allocator.h>
#endif
using namespace std;
int main() {
#ifdef __GNUC__
list <string, allocator<string>> c1;
list <string, __gnu_cxx::malloc_allocator<string>> c2;
list <string, __gnu_cxx::new_allocator<string>> c3;
list <string, __gnu_cxx::__pool_alloc<string>> c4;
list <string, __gnu_cxx::__mt_alloc<string>> c5;
list <string, __gnu_cxx::bitmap_allocator<string>> c6;
auto start = chrono::steady_clock::now();
char buf[10];
for (long i = 0; i < 10000; ++i) {
snprintf(buf, 10, "%d", i);
c2.push_back(string(buf));
}
auto end = chrono::steady_clock::now();
auto time = chrono::duration_cast<chrono::microseconds>(end - start).count();
std::cout << time;
#endif
}

标准接口

一组typedef: -allocator::value_type -allocator::pointer -allocator::const_pointer -allocator::reference -allocator::const_reference -allocator::size_type -allocator::difference_type

allocator::rebind allocator的内嵌模板,需要定义other成员 allocator::allocator() 构造函数 allocator::allocator(const allocator&) 拷贝构造函数 allocator::~allocator() 析构函数 pointer allocator::address(reference x)const 返回对象地址 pointer allocator::allocate(size_type n, const void *=0) 分配空间 void allocator::deallocator(pointer p, size_type n) 释放空间 size_type allocator::max_size() const 可以分配的最大空间 void allocator::construct(pointer p, const T&x) 构造分配内存中的对象 void allocator::destroy(pointer p) 析构内存对象

std::allocator

也就是new_allocator,对new/delete函数进行封装 源码剖析,推荐

bitmap_allocator 使用位来表示内存是否使用的分配器 debug_allocator 加入调试信息的分配器 malloc_allocator 简单地封装了malloc和free函数 pool_allcator 基于内存池的实现 throw_allocator 用于异常 mt_allocator 对多线程环境进行了优化

上述分配器的实现都在GNU的ext目录下,使用范例如下:

#include <ext/bitmap_allocator.h>
vector<int, __gnu_cxx::bitmap_allocator<int>> vec;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment