本文介绍的是一个简单的符合标准的allocator配置器,而在SGI STL中的allocator(实际叫alloc)配置器,这份allocator很简单,只是对::operator new和::operator delete的简单封装而已。下面的allocator完成对内存的分配与回收,但是并没有对象的构造,对象的构造是在stl_construct.h中的函数完成的,之所以将对象的分配和构造(析构和回收)分开,是为了提高效率,避免不必要的构造和对对象构造析构的优化,在使用下面的allocator配置器时,内存的分配和回收分别由allocator::allocate()和allocator::deallocate()负责,而对象的构造和析构则由::construct()和destroy()负责(位于stl_construct.h),这种分工使整个空间配置更灵活高效。但是SGI STL并未使用下面allocator,因为它效率不高,保留它是为了与HP STL风格兼容。SGI STL真正使用的是一个叫alloc的配置器,它在很多方面都与STL规范不同,但是性能卓越。将alloc和stl_construct中的construct(),destroy()结合,成为了SGI STL的特殊的空间配置器。
defalloc.h的源码:
// Filename: defalloc.h // Comment By: 凝霜 // E-mail: [email protected] // Blog: http://blog.csdn.net/mdl13412 /* * * Copyright (c) 1994 * Hewlett-Packard Company * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. Hewlett-Packard Company makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. * */ // 这个文件提供原始的HP默认allocator, 仅仅是为了向后兼容 // // 不要使用这个文件,除非你使用一个需要HP-style allocator的旧容器 // SGI STL使用一个不同的allocator接口 // SGI-style的allocator不针对对象类型进行参数化, 他使用void *指针 #ifndef DEFALLOC_H #define DEFALLOC_H #include <new.h> #include <stddef.h> #include <stdlib.h> #include <limits.h> #include <iostream.h> #include <algobase.h> // 如果内存分配失败, 则直接退出程序 template <class T> inline T* allocate(ptrdiff_t size, T*) { set_new_handler(0); T* tmp = (T*)(::operator new((size_t)(size * sizeof(T)))); if (tmp == 0) { cerr << "out of memory" << endl; exit(1); } return tmp; } template <class T> inline void deallocate(T* buffer) { ::operator delete(buffer); } // 标准的STL allocator接口 template <class T> class allocator { public: // STL type_traits需要的标准定义 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; pointer allocate(size_type n) { return ::allocate((difference_type)n, (pointer)0); } void deallocate(pointer p) { ::deallocate(p); } pointer address(reference x) { return (pointer)&x; } const_pointer const_address(const_reference x) { return (const_pointer)&x; } // size_type init_page_size() { return max(size_type(1), size_type(4096/sizeof(T))); } size_type max_size() const { return max(size_type(1), size_type(UINT_MAX/sizeof(T))); } }; // 仅使用void *类型的指针 class allocator<void> { public: typedef void* pointer; }; #endif