一个简单的空间配置器
STl源码剖析中的一个简单空间配置器
#ifndef _JJALLOC_ #define _JJALLOC_ #include <new> #include <cstdlib> #include <climits> #include <iostream> namespace JJ { template <typename T> inline T* _allocate(std::ptrdiff_t size, T*) { //为何要用ptrdiff类型,不应该有负数才对,T*的本意是用来保证空间局部性的参数,在这里并没有什么卵用 std::set_new_handler(0); //将set_new_handler置空,new失败时不做任何处理,直接返回nullptr T *tmp = (T*)(::operator new((size_t)(size * sizeof(T)))); //使用::operator new(size_t size) 分配空间 if (!tmp) { std::cerr << "out of memory" << std::endl; std::exit(1); //分配失败直接exit(1) } return tmp; } template <typename T> inline void _deallocate(T* buffer) { ::operator delete(buffer); //使用::operator delete(void *) 收回分配的空间 } template <typename T1, typename T2> inline void _construct(T1 *p, const T2&value) { new(p) T1(value); //使用placement new(void *) T(initialize) 在地址p处使用拷贝构造的方式直接构造对象 } template <typename T> inline void _destroy(T *ptr) { ptr->~T(); //在ptr出析构对象,但不回收内存 } template <typename T> //符合标准接口的简单分配器 class 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 std::ptrdiff_t difference_type; template <typename U> // 使用rebind可以得到这个模板的例外一个实例如: struct rebind { //allocator<int>::bind<string>::other stringAllocator; typedef allocator<U> other; }; pointer allocate(size_type n, const void *hint = 0) { //分配n个对象,hint是个提示符,需要的时候可以用来保持空间局部性 return _allocate((difference_type)n, (pointer)0); } void deallocate(pointer p, size_type n) { _deallocate(p); } void construct(pointer p, const T& value) { _construct(p, value); } void destroy(pointer p) { _destroy(p); } pointer address(reference x) { return (pointer)&x; } const_pointer const_address(reference x) { return (const_pointer)&x; } size_type max_size() const { return size_type(UINT_MAX/sizeof(T)); //因为size_type由unsigned int实现,所以最多可以分配UINT_MAX/sizeof(T)个T对象 } //如果需要更大的空间通常使用奇怪的类型外加在硬盘分配空间 }; } #endif // _JJALLOC_
看完代码,还有一些值得注意的地方:
空间配置器使用operator new与定位new分配空间并构造对象,所以可以直接使用set_new_handler(0)来指定new失败时的处理函数,然而在以malloc分配空间的地方,需要自己来实现这个机制
实际上SGI STL的空间配置器使用二级配置,并且都是使用malloc分配空间,底层使用地位new构造对象
浙公网安备 33010602011771号