您的位置:首页 > 其它

STL源码剖析之STL简介与STL配置器

2011-06-04 10:56 239 查看
1 从底层来看,STL带给我们一套具有实用价值的零部件,以及一个整合起来的整体,STL中组件之间耦合度很低,组件之间可以互相关联整合

2 STL以泛型思维,描述了很多抽象概念,以抽象概念为主体而不是依赖于实际的类

3 STL六大组件:

容器 : 数据结构(容纳数据)是一种class template

算法 : 常用的算法,是一种function template

迭代器:容器和算法之间的胶合剂,也是一种泛型组件,“泛型指针”,每个容器都有自己的迭代器,只有容器自己才知道如何使用自己的迭代器来完成迭代。

仿函数:类静态函数

适配器修饰容器或者仿函数或者迭代器接口的东西,也就是改变了被适配的东西,提供了新的接口

配置器空间配置和管理

4 六大组件的关系

Container通过allocator取得数据的存储空间,Algorithm通过Iterator 存取 container的内容,functor协助algorithm完成不同策略的变化,adapter可以修饰functor

5 allocator的简单定义

#include<cstddef>

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; //cstddef中的size_t,和ptrdiff_t

//存在于C标准库的头文件stddef的C++版cstddef

//size_t源类型是unsigned int,使用sizeof返回的类型就是size_t

//作用:avoid specifying machine-dependent data size,提高代码可移植性

typedef ptrdiff_t difference_type;

//两个指针差的类型,因为不一定和int一样,于平台有关。

template<class U>

struct rebind

{ typedef allocator<U> other;};

pointer allocater(size_type n, const void*hint=0) //分配空间

{

return _allocate( (difference_type)n, (pointer)0 ); //使用ptrdiff_t来得到独立于平台的地址差值

/* _allocate的实现

template<class T>

inline T* _allocate(ptrdiff_t size,T*)

{

T* tmp=(T*) (::operator new((size_t)(size*sizeof(T))) );

// C++中使用operator new来分配空间,注意这里使用的是size_t来作为空间大小的类型

if (tmp==0)

exit(1);

return tmp;

}

*/

//泛型思想,为特定大小的区间分配内存,返回指针

}

}

void deallocate(pointer p, size_type n)

{

_deallocate(p);

/*

template<class T>

inline void _deallocate(T* buffer) //泛型思想,operator delete

{

::operator delete(buffer);

}

*/

}

void construct(pointer p, const T& value) //构造对象

{

_construct(p,value);

/*

template<class T1,class T2>

inline void _construct(T1* p,const T2& value)

{

new(p) T1(value); //使用placement new

}

*/

}

void destroy(pointer p)

{

_destroy(p);

/*

template<class T>

inline void _destroy(T* ptr)

{

ptr->~T();

}

*/

}

pointer address(reference x)

{

return (pointer)&x; //返回对象的地址(指针)

}

const_pointer const_address(const_reference x);

{

return (const_pointer)&x;

}

size_type max_size() const

{

return size_type( UINT_MAX / sizeof(T) ); //可成功配置的最大

}

};

// vector<int, allocator<int> > iv(ia,ia+5);

// 底层上使用allocator来分配适当的空间,来存取数据等

6 SGI STL中的配置器是这样使用的std::alloc,而我们通常会使用缺省的空间配置器,所以SGI STL为每个容器都提供了默认参数说明空间配置器

Template<class T, class Alloc = alloc>

Class vector{};

7 [5]中所定义的allocator只是基层内存配置和释放(::operator new和::operator delete)的一层薄薄的包装,并没有考虑到效率上的优化。是SGI所定义的一个符合部分标准的配置器,

【6】中所说的是正式使用的alloc,是特殊的空间配置器,内部使用

8 配置器定义在memory文件中,而该文件包含了stl_alloc,stl_construct(一个完成内存分配,一个完成构造)

9 stl_construct的实现(内存配置前对象的构造行为)

<stl_construct.h>

#include<new.h>

template<class T1,class T2>

inline void construct(T1*p,const T2& value)

{

new(p) T1(value); // placement new 调用T1::T1(value)

}

template<class T>

inline void destroy(T* pointer) //接受单个指针,直接调用析构函数

{

pointer->~T();

}

template<class ForwardIterator>

inline void destroy(ForwardIterator first,ForwardIterator last)

//接受两个迭代器,删除区间对象

{

__destroy(first,last ,value_type(first);

//但是如果每个对象的析构函数都是trivial即无关痛痒的,就没必要一次一次调用析构

//所以这里使用value_type来获得对象的类型,再利用__type_trait<T>来判断是不是无关痛痒的

//这里是trait的用法,后面会说到

}

template<class ForwardIterator,class T>

inline void __destroy(ForwardIterator first,ForwardIterator last,T*)

{

typedef typename __type_trait<T>::has_trivial_destructor trivial_destructor;

__destroy_aux(first,last,trivial_destructor());

//根据传入的对象类型,使用tribial_destructor来判断是不是无关痛痒的

}

template<class ForwardIterator>

inline void __destroy_aux(ForwardIterator first,ForwardIterator last,__false_type)

{

for(;first<last;++first)

destroy(&*first);

}

template<class ForwardIterator>

inline void __destroy_aux(ForwardIterator,ForwardIterator,__true_type)

{ //释放内存空间

}

inline void destroy(char*,char*){}

inline void destroy(wchar_t*,wchar_t*){}









这是一种考虑到效率的construct和destroy!!!!!!因为在destroy时可以根据对象是否为trivial来调整destroy的策略

10 前面是内存配置后的 对象构造内存释放前的 对象析构,下面是具体的内存的配置和释放。

对象构造前的空间配置对象构造后的空间释放由<stl_alloc.h>负责。

在空间的配置和释放(alloc, 对象的构造construct)时要考虑:

1 堆空间申请

2 多线程情况

3 内存不足

4 内存碎片

C++的内存配置基本操作是::operator new() ::operator delete()这是两个“全局函数”,相当于C的malloc和free

下一篇将学习到SGI关于内存配置的策略。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: