自定义C++ STL内存分配器
第一种 自定义allocator
C++03时代的STL容器使用的是被称为分配器allocator的内存管理模块。
allocator是无状态(stateless)的,定义里没有成员变量,全是成员函数和一些typedef。
自定义allocator细节很多,尤其是那个rebind。
allocator是个画蛇添足的设计,提供了不必要的灵活性,增加了复杂度,增加了心智负担。
stl_mem.h
#pragma once
#include
#include
#include
stl_mem.cpp
#include "stl_mem.h"
using namespace MEM_STL;
memNode *mempool::m_free_head[32] = { 0 };
mutex mempool::m_mutex = { };
于是C++17引入了pmr(polymorphic memory resource 多态的内存资源)。
第二种 使用C++17提供的pmr
先看一种非常简单的内存分配实现:
char *buf = 0;
const int max_size = 1024000;
int len = 0;
void *new_(size_t t){
void *p = 0;
if (t + len < max_size){
p = &buf[len];
len += (t + 4);
}
return p;
}
void free_(void *p){}
class buf_helper{
public:
buf_helper(){
buf = new char[max_size];
}
~buf_helper(){
delete buf;
}
};
buf_helper g_buf_helper;
new一块内存,中途只使用不回收,最后一次性delete掉。
pmr就是这种思路。C++17 pmr
点击查看代码
#include
#include
#include
#include
#include
char *buf = 0;
const int max_size = 1024000;
int len = 0;
void *new_(size_t t)
{
void *p = 0;
if (t + len < max_size)
{
p = &buf[len];
len += (t + 4);
}
return p;
}
void free_(void *p)
{
}
class buf_helper
{
public:
buf_helper()
{
buf = new char[max_size];
}
~buf_helper()
{
delete buf;
}
};
buf_helper g_buf_helper;
class debug_resource : public std::pmr::memory_resource
{
public:
explicit debug_resource(std::pmr::memory_resource *up = std::pmr::get_default_resource())
: _upstream{ up }
{
}
void *do_allocate(size_t bytes, size_t alignment) override
{
std::cout << " do_allocate(): " << bytes << '\n';
return _upstream->allocate(bytes, alignment);
}
void do_deallocate(void *ptr, size_t bytes, size_t alignment) override
{
std::cout << " do_deallocate(): " << bytes << '\n';
_upstream->deallocate(ptr, bytes, alignment);
}
bool do_is_equal(const std::pmr::memory_resource &other) const noexcept override
{
std::cout << " do_is_equal(): " << '\n';
return this == &other;
}
private:
std::pmr::memory_resource *_upstream;
};
int main()
{
char buffer[32] = {};
std::fill_n(std::begin(buffer), std::size(buffer) - 1, '_');
std::cout << buffer << '\n';
debug_resource dr;
std::pmr::monotonic_buffer_resource pool{ std::data(buffer), std::size(buffer) ,&dr };
std::pmr::vector vec{ &pool };
//vec.reserve(26);
for (char ch = 'a'; ch <= 'z'; ++ch)
{
vec.push_back(ch);
std::cout << buffer << '\n';
}
std::cout << buffer << '\n';
}
核心代码
char buffer[32] = {};
memory_resource dr;
std::pmr::monotonic_buffer_resource pool{ std::data(buffer), std::size(buffer) ,&dr };
std::pmr::vector vec{ &pool };
pmr::memory_resource 决定内存来源
monotonic buffer resource
unsynchronized_pool_resource
synchronized_pool_resource
pmr::polymorphic_allocator 负责内存分配
名字中的polymorphic是说:这个新的分配器的行为会表现出多态,与以前的分配器不同。
新分配器和stl分配器兼容。保存了一个memory_resource的指针,所以是有状态的(statefull)。
外界需要保证memory_resource指针的生命周期。
polymorphic_allocator 就是把Memory_resource适配成Alloctor。
pmr是专门用来提高c++内存性能的!一般应用,对pmr的需求没有那么强烈。
一句话:内存局部性原理
可以细读这篇文章:游戏引擎开发新感觉!(6) c++17内存管理