新乡网站推广,郑州模板网站制作,网站海外推广技巧,洮南网站建设哪家专业怎么有效的手撕代码呢#xff1f; gnu gcc 2.9 的 内存池
把代码跑起来把代码一个片段拿出来使用画出代码运行的流程图一行一行的搬运在看源码的情况下写出类似的demo
第三步#xff1a;
第五步: // 这个头文件包含一个模板类 allocator#xff0c;用于管理内存的分配、…怎么有效的手撕代码呢 gnu gcc 2.9 的 内存池
把代码跑起来把代码一个片段拿出来使用画出代码运行的流程图一行一行的搬运在看源码的情况下写出类似的demo
第三步
第五步: // 这个头文件包含一个模板类 allocator用于管理内存的分配、释放对象的构造、析构
//TODO: debug
/*全大写为 define const enum
成员变量 M开头
全局变量 G开头
static S开头
内部使用 “__”开头为内部私有函数变量或者同名的包函数 “_”为其他的一般内部部分 注变量常为“__”*/
#pragma once#include new // for placement new
#include cstddef // for ptrdiff_t size_t
#include cstdlib // for exit
#include climits // for UINT_MAX
#include iostream // for cerrenum { ALIGN 8 };
enum { MAX_BYTES 128 };
enum { NFREELISTS MAX_BYTES / ALIGN };#define FREE_INDEX(args) (args/ALIGN -1)
#define UP_ROUND(args) ((argsALIGN-1) ~(ALIGN -1))#if 0
# include new
# define __THROW_BAD_ALLOC throw bad_alloc()
#elif !defined(__THROW_BAD_ALLOC)
# include iostream
# define __THROW_BAD_ALLOC cerr out of memory endl; exit(1)
#endifnamespace kstd
{/*new 处理函数set_new_handler()是为分配函数在凡是内存分配尝试失败时调用的函数。其目的是三件事之一1) 令更多内存可用2) 终止程序例如通过调用 std::terminate3) 抛出 std::bad_alloc 或自 std::bad_alloc 导出的类型的异常。*///创建内存template class Tinline T* __allocate(size_t size){return (T)malloc(size);}//销毁内存template class Tinline void __deallocate(T* buffer){free(buffer);}//构造函数 placement newtemplate class T1, class T2inline void __construct(T1* p, const T2 value){new (p) T1(value);}template class Tinline void __construct(T* ptr){new (ptr) T;}//析构template class Tinline void __destroy(T* ptr){ptr-~T();}// 模板类allocator// 模板函数代表数据类型template class Tclass allocator{public:typedef T value_type;typedef T* pointer;typedef const T* const_pointer;typedef T reference;typedef const T const_reference;typedef size_t size_type;typedef ptrdiff_t difference_type;private:union _obj {_obj* next;char unuse[1];};static size_t _S_heap_size;_obj* free_list[] { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };_obj* start, * end;public:static pointer allocate(size_type n){size_type size UP_ROUND(n);if(sizeMAX_BYTES)__allocate((size_type)n);else {_obj** indexfree_list FREE_INDEX(size);_obj* result *index;if (0 result) {return refill(size);}*index result-next;return result;}}static pointer refill(size_type n){int nobj 20;char* chunk alloc_chunk(n,nobj);//这里会爆出异常 __THROW_BAD_ALLOCif (1 nobj)return chunk;/*for (__i 1; ; __i) {__current_obj __next_obj;__next_obj (_Obj*)((char*)__next_obj __n);if (__nobjs - 1 __i) { __current_obj-_M_free_list_link 0;break;//gnu gcc不喜欢正常循环20次 喜欢直接break出}else {__current_obj-_M_free_list_link __next_obj;}}*///_obj** index free_list FREE_INDEX(size);_obj* result,*current;result chunk;_obj* pro (_obj*)((char*)chunk size);current pro;//哨兵for (int i 1; i nobj; i) {pro (_obj*)((char*)chunk size);//这里不强制转换可能跳的数量不对 每次跳sizeof(char) 位才对current-next pro;current pro;}current-next nullptr;return result;}static size_type alloc_chunk(size_type __size, int __nobjs) {/*四种情况先看看能不能从pool里面割出20个20是经验值 就如vector扩容有时是2倍有时是1.5倍不能看看能不能割出一个一个都不能看看能不能往池子里装水还是不能就调用一级适配器调用malloc让操作系统想办法*/size_type left_bytes end - start ;//水池剩下的水size_type total_bytes __size*__nobjs;_obj* result;if (left_bytes total_bytes) {result start;start start total_bytes;return result;}else if (left_bytes __size) {__nobjs (int)(left_bytes/__size);total_bytes __size * __nobjs;result start;start start total_bytes;return result;}else {size_t __bytes_to_get 2 * total_bytes UP_ROUND(_S_heap_size 4);_obj** __my_free_list;if (left_bytes 0) {__my_free_list free_list FREE_INDEX(left_bytes);((_obj*)start)-next *__my_free_list;*__my_free_list (_obj*)start;}start (char*)__allocate(__bytes_to_get);if (0 start) {_obj* __p;for (auto __i __size; __i MAX_BYTES;iALIGN ) {__my_free_list free_list FREE_INDEX(__i);__p *__my_free_list;if (0 ! __p) {start __p;end __p __i;__p __p-next;return(alloc_chunk(__size, __nobjs));}}//山穷水尽 因为前面就是malloc的 没必要再试了 直接报错__THROW_BAD_ALLOC}}}//static void deallocate(pointer ptr);};} // namespace kstd