现在的位置: 首页 > 综合 > 正文

一步一步写STL:多级空间配置器(上)

2013年08月30日 ⁄ 综合 ⁄ 共 2260字 ⁄ 字号 评论关闭

在前一篇空间配置器里我给出了一个标准STL空间配置器的接口,说明了4个函数的工作原理,具体在标准空间配置器,注意那只是一个标准接口,无论是HP版本还是微软的STL版本都支持那些接口,所以我们测试的时候没出任何问题!他实际上就是对全局的operator new 和 operator delete做了一个浅浅的包装,并没有什么效率和技巧上的优化,但是在SGI版本的STL里面,并没有采用那种分配方式,而是实现了一系列更高级的内存管理办法,但也保留了老式的标准接口,但他从未使用过,也不推荐我们使用,

 

在继续写空间配置器之前,我先总结下SGI配置器的实现原理,我也将采用它的方式模拟

这个过程我准备了3个步骤:

1:解析SGI空间配置器的整体实现方式    (也就是这篇,参照STL源码剖析)

2:解析SGI中的第二级分配器实现原理    (也参照STL源码剖析)

3:动手模拟写出多级分配器

 

如下为SGI保留的标准接口实现方式:

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); 
}  

template <class 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 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))); 
        } 
};  

//注意这里没有template<>这样的语句,不懂的看源码剖析的组态
class allocator<void>
{
    typedef void* pointer; 
};  

上面这个配置器接口跟我自己提供的提供的差不多,也是使用的C++方式实现,其中有个set_new_handler函数,(这里假设都知道了这个函数,不知道的参见effective C++) 这个接口在SGI版本里面并没有被采用,而是取而代之用一种新的,采用C语言方式实现的特殊配置器名叫alloc!

一般而言,我们所使用new和delete为对象分配空间和销毁空间的时候可以细分为4步:

1:申请一定的空间,用operator new完成

2:在该空间上调用构造函数初始化 这两步是new完成的操作

3:调用析构函数销毁对象
4:调用operator delete释放空间  这两步在delete完成

 

为了精密分工,STL   allocator决定将这两阶段动作区分开来。

内存配置动作由alloc:allocate()负责,内存释放动作由alloc::deallocate()负责;

对象建构动作由::construct()负责,对象解构动作由::destroy()负责

 

SGI   <memory>内含以
下两个文件:
#include <stl_alloc.h>                //负责内存空间的配置与释放
#include <stl_construct.h>         //负责对象内容的建构与解构

图示如下:

 

 由上图可以清楚的看到对象构造和析构以及内存的分配与释放的文件分布,至于第三个文件主要是起辅助作用,配合更好的工作,说到这里插一个题外话,一般编译器比如vs里面配置的STL并不是SGI版本的STL,据我所知只有GCC才是,windows下的如果要想获得SGI源码,可以去STLport网站去下载一份完整的源码,显示软件推荐notepad++,因为他的显示效果很好,这里我已经下载了,打开stl_construct.h文件显示效果如下:

图示如下:

这里面有对象构造和析构的各种情况,很容易看懂,这里就不累述了,配合侯捷的源码剖析看起来就简单多了,相比之下stl_alloc.h文件下的分布就复杂多了,里面有两个分配器,也就是所说的一级内存和二级内存分配器,一级分配相对简单,但是二级涉及到一系列自由列表算法,下一篇将用整篇来总结,到饭点了,到此为止!

 

 

 

 

 

 

 

抱歉!评论已关闭.