最近在复习STL,感觉再看的时候比刚开始学的时候通透很多。以前模拟实现了一个STL库,最近复习完又重构了一遍。代码放出来以供后面学习。如果有写的不好的地方欢迎大家批评指正。

STL_List.h

 #pragma once
#include"STL_Iterator.h" template<class T>
struct _List_Node
{
_List_Node* _prev;
_List_Node* _next;
T _data;
_List_Node()
{ }
_List_Node(const T& x)
:_data(x)
, _prev(NULL)
, _next(NULL)
{ }
}; template<class T, class Ref, class Ptr>
struct _List_Iterator
{
typedef BidirectionalIterator_tag IteratorCategory;
typedef _List_Iterator<T, T&, T*> Iterator;
typedef T ValueType;
typedef T& Reference;
typedef T* Pointer;
typedef _List_Node<T> *LinkType;
typedef _List_Iterator<T, Ref, Ptr> Self;
typedef int DifferenceType;
LinkType _node; _List_Iterator()
{ }
_List_Iterator(LinkType x)
:_node(x)
{
}
Reference operator*()
{
return _node->_data;
}
Pointer operator->()
{
return &(_node->_data);
}
Iterator operator++()
{
_node = _node->_next;
return *this;
}
Iterator operator++(int)
{
Iterator tmp;
tmp = *this;
_node = _node->_next;
return tmp;
} Iterator operator--()
{
_node = _node->_prev;
return *this;
}
Iterator operator--(int)
{
Iterator tmp = *this;
_node = _node->_prev;
return tmp;
} bool operator!=(const Self& x)
{
return _node != x._node;
} bool operator==(const Self& x)
{
return _node == x._node;
} }; template<class T, class Alloc = Alloc>
class List
{
public:
typedef _List_Node<T>* LinkType;
typedef _List_Iterator<T, T&, T*> Iterator;
typedef SimpleAlloc<_List_Node<T>, Alloc> ListNodeAllocator; List()
{
_node = new _List_Node<T>();
_node->_next = _node;
_node->_prev = _node;
}
~List()
{
Destory(Begin(), End());
Iterator it = Begin();
while (it != End())
{
ListNodeAllocator::Deallocate(it._node);
}
} Iterator Begin()
{
return _node->_next;
} Iterator End()
{
return _node;
} Iterator Insert(Iterator pos, const T& x)
{
LinkType prev = pos._node->_prev;
LinkType tmp = ListNodeAllocator::Allocate();
Construct(tmp, x);
//LinkType tmp = new _List_Node<T>(x);
prev->_next = tmp;
pos._node->_prev = tmp;
tmp->_next = pos._node;
tmp->_prev = prev;
return tmp;
} void PushBack(const T& x)
{
Insert(End(), x);
} void PushFront(const T& x)
{
Insert(Begin, x);
} //reverse
//remove
//empty
//size
//unique
//merge
protected:
LinkType _node;
}; void TestList()
{
List<int> l;
l.PushBack();
l.PushBack();
l.PushBack();
l.PushBack();
l.PushBack(); List<int>::Iterator it;
List<int>::Iterator begin = l.Begin();
List<int>::Iterator end = l.End();
for (it = l.Begin(); it != l.End(); it++)
{
cout << *it << " ";
}
cout << "Distance" << Distance(begin, end) << endl;
}

STL_Vector.h

 #pragma once
#include<cassert>
#include"STL_Iterator.h"
#include"STL_Alloc.h"
#include"STL_Construct.h"
#include"STL_Uninittialized.h" template<class T, class Alloc = Alloc>
class Vector
{
typedef T ValueType;
typedef T& Reference;
typedef T* Pointer;
typedef int DifferenceType;
public:
typedef ValueType * Iterator;
typedef RandomAccessIterator_tag IteratorCategory;
typedef SimpleAlloc<T, Alloc> DataAlloc; Iterator Begin() { return Start; }
Iterator End() { return Finish; } Vector()
:Start(NULL)
, Finish(NULL)
, EndOfStorage(NULL)
{ }
Vector(size_t n, const T& value)
{
Start = new T[n];
Finish = Start + n;
EndOfStorage = Finish;
}
~Vector()
{
Destory(Start, Finish);
DataAlloc::Deallocate(Start, Size());
} /*void Insert(Iterator Position,size_t n,const ValueType& x)
{
if (n != 0)
{
if (size_t(EndOfStorage - Finish) > n)
{
size_t Elems_After = Finish - Position;
Iterator OldFinish = Finish;
if (Elems_After > n)
{
Finish += n;
Copy_Backward(Position, OldFinish - n, OldFinish);
while (n-- > 0)
{
*(Position++) = x;
}
}
else
{
int tmp = n - Elems_After;
while (tmp-- > 0)
{
*(Finish++) = x;
}
tmp = OldFinish - Position;
for (int i = 0; i < tmp; ++i)
{
*(Finish++) = *(Position + i);
}
while (n-- > 0)
{
*(Position++) = x;
}
}
}
else
{
ExpandCapacity();
Insert(Position, n, x);
}
}
}*/
void Push_Back(const T& x)
{
ExpandCapacity();
Construct(Finish, x);
Finish++; }
void Pop_Back()
{
assert(Size());
Destory(Finish);//ÓбØҪô£¿£¿
--Finish;
}
size_t Size()
{
return (Finish - Start);
} bool Empty()
{
return Beign == End;
} Iterator Erase(Iterator pos)
{
Iterator begin = pos;
wihle(begin + != Finish)
{
*begin = *(beign + );
}
--Finish;
return pos;
} protected: void Copy_Backward(Iterator Position, Iterator first, Iterator last)
{
while (first != Position - )
{
*(last--) = *(first--);
} }
void ExpandCapacity()
{
if (Finish == EndOfStorage)
{
size_t size = Size();
size_t curLength = EndOfStorage - Start;
size_t newLength = * curLength + ;
T *tmp = DataAlloc::Allocate(newLength);
if (Start)
{
UninitializedCopy(Start, Start + size, tmp);
}
Destory(Start, Finish);
DataAlloc::Deallocate(Start, EndOfStorage - Start); Start = tmp;
Finish = Start + Size();
EndOfStorage = Start + newLength; /* Iterator newStart = new T[newLength];
Iterator it = Begin();
for (int i = 0; i < Size(); ++i)
{
newStart[i] = Start[i];
}
Destory();
Start = newStart;
Finish = Start + curLength;
EndOfStorage = Start + newLength;*/
}
}
//void Destory()
//{
// delete[] Start;
// Start = NULL;
// Finish = NULL;
// EndOfStorage = NULL;
//}
protected:
Iterator Start;
Iterator Finish;
Iterator EndOfStorage;
}; void TestVector()
{
Vector<int> v;
v.Push_Back();
v.Push_Back();
v.Push_Back();
v.Push_Back();
v.Push_Back();
Vector<int>::Iterator cur;
for (cur = v.Begin(); cur != v.End(); cur++)
{
cout << *cur << " ";
}
}
vector的数据安排和数组非常相似。两者的差别在于数组是静态空间,一旦配置了就不能改变,而vector是动态空间,随着元素的加入,他的内部会自行扩充空间(自行扩充不是在原有空间上 续接新空间,因为无法保证原空间之后还有可供配置的空间,所以他会重新开辟一块原大小二倍的空间,然后将原来的数据拷贝过来,然后在原内容之后构造新元素,并释放原有空间)。一旦vector旧有空间满载,内部只是扩充一个元素的空间实为不智,因为配置新空间,数据移动,释放原空间成本很高,应该加入某种未雨绸缪的考虑,在STL中就是空间扩大原来的二倍。
 
数组和链表的区别:
  • 数组是将元素在内存中连续存放,由于每个元素占用内存相同,可以通过下标迅速访问数组中任何元素。但是如果要在数组中增加一个元素,需要移动大量元素,在内存中空出一个元素的空间,然后将要增加的元素放在其中。同样的道理,如果想删除一个元素,同样需要移动大量元素去填掉被移动的元素。如果应用需要快速访问数据,很少或不插入和删除元素,就应该用数组。
  • 链表恰好相反,链表中的元素在内存中不是顺序存储的,而是通过存在元素中的指针联系到一起。比如:上一个元素有个指针指到下一个元素,以此类推,直到最后一个元素。如果要访问链表中一个元素,需要从第一个元素开始,一直找到需要的元素位置。但是增加和删除一个元素对于链表数据结构就非常简单了,只要修改元素中的指针就可以了。如果应用需要经常插入和删除元素你就需要用链表数据结构了。
   *C++语言中可以用数组处理一组数据类型相同的数据,但不允许动态定义数组的大小,即在使用数组之前必须确定数组的大小。而在实际应用中,用户使用数组之前有时无法准确确定数组的大小,只能将数组定义成足够大小,这样数组中有些空间可能不被使用,从而造成内存空间的浪费。链表是一种常见的数据组织形式,它采用动态分配内存的形式实现。需要时可以用new分配内存空间,不需要时用delete将已分配的空间释放,不会造成内存空间的浪费。
  (1) 从逻辑结构角度来看
     a, 数组必须事先定义固定的长度(元素个数),不能适应数据动态地增减的情况。当数据增加时,可能超出原先定义的元素个数;当数据减少时,造成内存浪费。
     b,链表动态地进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据项。(数组中插入、删除数据项时,需要移动其它数据项)
  (2)从内存存储角度来看
     a,(静态)数组从栈中分配空间, 对于程序员方便快速,但自由度小。
     b, 链表从堆中分配空间, 自由度大但申请管理比较麻烦.

STL_Uninitialized.h

 #pragma once
#include"STL_Iterator.h"
#include"TypeTraits.h"
#include"STL_Construct.h"
#include"STL_Iterator.h"
#include<memory.h> template <class InputIterator, class ForwardIterator>
inline ForwardIterator
__UninitializedCopyAux(InputIterator first, InputIterator last,
ForwardIterator result,
__TrueType) {
return copy(first, last, result);
} template <class InputIterator, class ForwardIterator>
ForwardIterator
__UninitializedCopyAux(InputIterator first, InputIterator last,
ForwardIterator result,
__FalseType) {
ForwardIterator cur = result; for (; first != last; ++first, ++cur)
Construct(&*cur, *first);
return cur;
} template <class InputIterator, class ForwardIterator, class T>
inline ForwardIterator __UninitializedCopy(InputIterator first, InputIterator last,
ForwardIterator result, T*)
{
typedef typename __TypeTraits<T>::IsPODType IsPOD;
return __UninitializedCopyAux(first, last, result, IsPOD());
} template <class InputIterator, class ForwardIterator>
inline ForwardIterator UninitializedCopy(InputIterator first, InputIterator last,
ForwardIterator result) {
return __UninitializedCopy(first, last, result, ValueType(result));
} inline char* UninitializedCopy(const char* first, const char* last,
char* result) {
memmove(result, first, last - first);
return result + (last - first);
} inline wchar_t* UninitializedCopy(const wchar_t* first, const wchar_t* last,
wchar_t* result) {
memmove(result, first, sizeof(wchar_t)* (last - first));
return result + (last - first);
}

STL_Construct.h

 #pragma once

 #include"TypeTraits.h"

 template<class T>
inline void Destory(T *pointer)
{
pointer->~T();
} template<class T1, class T2>
inline void Construct(T1 *p, const T2& value)
{
new(p)T1(value);
} template<class ForwardIterator>
inline void __DestoryAux(ForwardIterator first, ForwardIterator last, __FalseType)
{
for (; first < last; ++first)
{
Destory(&*first);
}
} template<class ForwardIterator>
inline void __DestoryAux(ForwardIterator first, ForwardIterator last, __TrueType)
{} template<class ForwardIterator, class T>
inline void __Destory(ForwardIterator first, ForwardIterator last, T *)
{
typedef typename __TypeTraits<T>::HasTrivialDestructor TrivialDestructor;
__DestoryAux(first, last, TrivialDestructor());
} template<class ForwardIterator>
inline void Destory(ForwardIterator first, ForwardIterator last)
{
__Destory(first, last, ValueType(first));
} inline void Destory(char*, char*) {}
inline void Destory(wchar_t*, wchar_t*) {}

STL_Alloc.h

 #pragma once

 template<class T, class Alloc>
class SimpleAlloc
{
public:
static T *Allocate(size_t n)
{
return == n ? : (T*)Alloc::Allocate(n * sizeof(T));
}
static T *Allocate(void)
{
return (T*)Alloc::Allocate(sizeof(T));
}
static void Deallocate(T *p, size_t n)
{
if ( != n) Alloc::Deallocate(p, n * sizeof(T));
}
static void Deallocate(T *p)
{
Alloc::Deallocate(p, sizeof(T));
}
}; template<int inst>
class __MallocAllocTemplate//一级配置器
{
private:
static void *OomMalloc(size_t n)
{
void(*MyMallocHandler)();//期待可以通过用户设置的handler解决内存不足问题(释放一部分内存)
void *result; while ()
{
MyMallocHandler = __MallocAllocOomHandler;
if ( == MyMallocHandler)
{
cout << "别开辟了,实在没有了(此处应该抛出异常)" << endl;
exit(-);
}
(*MyMallocHandler)();
result = malloc(n);
if (result) return(result);
}
}
static void *OomRealloc(void *ptr, size_t n)
{
void(*MyMallocHandler)();//期待可以通过用户设置的handler解决内存不足问题(释放一部分内存)
void *result; while ()
{
MyMallocHandler = __MallocAllocOomHandler;
if ( == MyMallocHandler)
{
cout << "别开辟了,实在没有了(此处应该抛出异常)" << endl;
exit(-);
}
(*MyMallocHandler)();
result = realloc(p, n);
if (result) return(result);
}
}
static void(*__MallocAllocOomHandler)();//定义函数指针,其实没啥用
public:
static void *Allocate(size_t n)
{
void *result = malloc(n);
if ( == result)
{
result = OomMalloc(n);
}
return result;
}
static void Deallocate(void *p, size_t n)//后面的n似乎用处不大
{
free(p);
}
static void *Reallocate(void *p, size_t oldsize, size_t newsize)
{
void *result = realloc(p, newsize);
if ( == result)
{
result = OomRealloc(p, newsize);
}
return result;
}
static void(*SetMallocHandler(void(*f)()))()
{
void(*old)() = __MallocAllocOomHandler;
__MallocAllocOomHandler = f;
return(old);//设置新的处理函数指针,返回旧的函数指针
} };
template <int inst>
void(*__MallocAllocTemplate<inst>::__MallocAllocOomHandler)() = ;//所以说那个函数指针一般没啥用都设为NULL了 typedef __MallocAllocTemplate<> MallocAlloc; # ifdef __USE_MALLOC typedef malloc_alloc Alloc;
# else template<bool threads, int inst>
class __DefaultAllocTemplate//二级空间配置器含有内存池
{
enum { __ALIGN = };
enum { __MAX_BYTES = };
enum { __NFREELISTS = __MAX_BYTES / __ALIGN };
private: static size_t ROUND_UP(size_t bytes) {
return (((bytes)+__ALIGN - ) & ~(__ALIGN - ));
}
union Obj {
union Obj * FreeListLink;
char ClientData[]; /* The client sees this. */
}; static Obj * volatile FreeList[__NFREELISTS];//声明自由链表
static char *StartFree;
static char *EndFree;
static size_t HeapSize; static size_t FREELIST_INDEX(size_t bytes) {
return (((bytes)+__ALIGN - ) / __ALIGN - );
} static void *Refill(size_t n)
{
int nobjs = ;
char *chunk = ChunkAlloc(n, nobjs);
Obj* volatile MyFreeList;
Obj* result;
int i;
if ( == nobjs)
{
return chunk;
}
int index = FREELIST_INDEX(n);
MyFreeList = FreeList[index];
result = (Obj *)chunk;
MyFreeList = (Obj *)(chunk + n);//取出剩下的节点挨个儿查到对应的自由链表位置上去
Obj* end = (Obj *)MyFreeList;
for (i = ;; i++)
{
if (nobjs - == i)
{
end->FreeListLink = ;
break;
}
else
{
end->FreeListLink = (Obj *)(chunk + (i + )*n);
}
}
return result;
}
static char *ChunkAlloc(size_t size, int &nobjs)
{
char *result;
size_t totalbytes = size*nobjs;
size_t bytesleft = EndFree - StartFree;
if (bytesleft >= totalbytes)//内存池的内存完全够用
{
result = StartFree;
StartFree += totalbytes;
return result;
}
else if (bytesleft >= size)//内存池的内存虽然不够20个,但是至少够1个
{
nobjs = bytesleft / size;
totalbytes = nobjs*size;
result = StartFree;
StartFree += totalbytes;
return result;
}
else
{
size_t bytestoget = * totalbytes + ROUND_UP(HeapSize >> );
if (bytesleft > )//还有一部分内存没有分配,需要先分配出去
{
int index = FREELIST_INDEX(bytesleft);
Obj * volatile MyFreeList = FreeList[index];
Obj *tmp = (Obj *)StartFree;
tmp->FreeListLink = MyFreeList;//头插
MyFreeList = tmp;
}
StartFree = (char *)malloc(bytestoget);
if ( == StartFree)
{
int i;
Obj *volatile MyFreeList, *p;
for (i = size; i <= __MAX_BYTES; i += __ALIGN) {
int index = FREELIST_INDEX(i);
MyFreeList = FreeList[index];
p = MyFreeList;
if ( != p)
{
MyFreeList = p->FreeListLink;
StartFree = (char *)p;
EndFree = StartFree + i;
return(ChunkAlloc(size, nobjs));
}
}
EndFree = ;
StartFree = (char *)MallocAlloc::Allocate(bytestoget); }
HeapSize += bytestoget;
EndFree = StartFree + bytestoget;
return (ChunkAlloc(size, nobjs));
}
} public:
static void *Allocate(size_t n)
{
Obj* volatile MyFreeList;
Obj* result;
if (n > (size_t)__MAX_BYTES)//大于128字节到一级配置器中去
{
return MallocAlloc::Allocate(n);
}
int index = FREELIST_INDEX(n);
MyFreeList = FreeList[index];
result = MyFreeList;
if (result == )
{
void *r = Refill(ROUND_UP(n));
return r;
}
MyFreeList = result->FreeListLink;
return result;
} static void Deallocate(void *p, size_t n)
{
int index = FREELIST_INDEX(n);
Obj* q = (Obj *)p;
Obj* volatile MyFreeList;
if (n > (size_t)__MAX_BYTES)
{
MallocAlloc::Deallocate(p, n);
return;
}
MyFreeList = FreeList[index];//把内存块还给自由链表,采用头插的方式插入自由链表
q->FreeListLink = MyFreeList;
MyFreeList = q; } };
template <bool threads, int inst>
typename __DefaultAllocTemplate<threads, inst>::Obj* volatile __DefaultAllocTemplate<threads, inst>::FreeList[__DefaultAllocTemplate<threads, inst>::__NFREELISTS]; template <bool threads, int inst>
char* __DefaultAllocTemplate<threads, inst>::StartFree = ;
template <bool threads, int inst>
char* __DefaultAllocTemplate<threads, inst>::EndFree = ;
template <bool threads, int inst>
size_t __DefaultAllocTemplate<threads, inst>::HeapSize = ;; typedef __DefaultAllocTemplate<, > Alloc; #endif void Test1()
{
// 测试调用一级配置器分配内存
cout << "测试调用一级配置器分配内存" << endl;
char*p1 = SimpleAlloc<char, Alloc>::Allocate();
SimpleAlloc<char, Alloc>::Deallocate(p1, ); // 测试调用二级配置器分配内存
cout << "测试调用二级配置器分配内存" << endl;
char*p2 = SimpleAlloc<char, Alloc>::Allocate();
char*p3 = SimpleAlloc<char, Alloc>::Allocate();
char*p4 = SimpleAlloc<char, Alloc>::Allocate();
char*p5 = SimpleAlloc<char, Alloc>::Allocate();
SimpleAlloc<char, Alloc>::Deallocate(p2, );
SimpleAlloc<char, Alloc>::Deallocate(p3, );
SimpleAlloc<char, Alloc>::Deallocate(p4, );
SimpleAlloc<char, Alloc>::Deallocate(p5, ); for (int i = ; i < ; ++i)
{
printf("测试第%d次分配\n", i + );
char*p = SimpleAlloc<char, Alloc>::Allocate();
}
}
空间配置器是为了解决内存碎片的问题。由于在堆中频繁申请释放内存,造成外碎片的问题,(极端情况下,就是堆中空闲的内存总量满足一个需求,但是这些内存都不连续,导致任何的一个单独块的内存都无法满足这个请求。
STL中使用两级空间配置器。当申请的内存大于128字节时,认为申请的是大内存,调用一级空间配置器来分配内存,当申请的内存小于等于128字节则认为申请的是小内存,调用二级空间配置器去内存池中申请。一级空间配置器很简单,直接封装了malloc和free来实现 。二级空间配置器是使用内存池+自由链表来实现的。
为了便于管理,二级空间配置器都是以8的倍数对齐,方便内存管理。这样的话需要维护16个自由链表,这16个自由链表管理的内存大小分别为8,16,24,32,。。128字节的空间。
二级空间配置器的逻辑步骤:
如果现在要申请那个字节的空间是否大于128,如果大于128则直接调用一级空间配置器,如果不大于将n上调至8的倍数,然后在去自由链表中响应的节点下面找,如果该节点下面挂有还未使用的内存,则摘下来直接返回这块空间的地址。否则的话我们就要调用refill函数去内存池中申请

STL_Iterator.h

 #pragma once

 struct InputIterator_tag {};
struct OutputIterator_tag {};
struct ForwardIterator_tag : public InputIterator_tag {};
struct BidirectionalIterator_tag : public ForwardIterator_tag {};
struct RandomAccessIterator_tag : public BidirectionalIterator_tag {}; template <class T, class Distance> struct InputIterator {
typedef InputIterator_tag IteratorCategory;
typedef T ValueType;
typedef Distance DifferenceType;
typedef T* Pointer;
typedef T& Reference;
}; struct OutputIterator {
typedef OutputIterator_tag IteratorCategory;
typedef void ValueType;
typedef void DifferenceType;
typedef void Pointer;
typedef void Reference;
}; template <class T, class Distance> struct ForwardIterator {
typedef ForwardIterator_tag IteratorCategory;
typedef T ValueType;
typedef Distance DifferenceType;
typedef T* Pointer;
typedef T& Reference;
}; template <class T, class Distance> struct BidirectionalIterator {
typedef BidirectionalIterator_tag IteratorCategory;
typedef T ValueType;
typedef Distance DifferenceType;
typedef T* Pointer;
typedef T& Reference;
}; template <class T, class Distance> struct RandomAccessIterator {
typedef RandomAccessIterator_tag IteratorCategory;
typedef T ValueType;
typedef Distance DifferenceType;
typedef T* Pointer;
typedef T& Reference;
}; template <class Category, class T, class Distance = size_t, class Pointer = T*, class Reference = T&>
struct Iterator {
typedef Category IteratorCategory;
typedef T ValueType;
typedef Distance DifferenceType;
typedef Pointer Pointer;
typedef Reference Reference;
}; template <class Iterator>
struct IteratorTraits
{
typedef typename Iterator::IteratorCategory IteratorCategory;
typedef typename Iterator::ValueType ValueType;
typedef typename Iterator::DifferenceType DifferenceType;
typedef typename Iterator::Pointer Pointer;
typedef typename Iterator::Reference Reference;
};//ÀàÐÍÝÍÈ¡»ú template <class T>
struct IteratorTraits<T*>
{
typedef RandomAccessIterator_tag IteratorCategory;
typedef T ValueType;
typedef ptrdiff_t DifferenceType;
typedef T* Pointer;
typedef T& Reference;
}; template<class InputIterator>
int Distance(InputIterator first, InputIterator last)
{
return _Distance(first, last, IteratorTraits<InputIterator>::IteratorCategory());
} template<class InputIterator>
int _Distance(InputIterator first, InputIterator last, ForwardIterator_tag)
{
int count = ;
while (first != last)
{
count++;
first++;
}
return count;
} template<class InputIterator>
int _Distance(InputIterator first, InputIterator last, RandomAccessIterator_tag)
{
return last - first;
} //template <class Iterator>
//inline typename IteratorTraits<Iterator>::DifferenceType*
//DifferenceType(const Iterator&) {
// return static_cast<typename IteratorTraits<Iterator>::DifferenceType*>(0);
//} template <class T, class Distance>
inline T* ValueType(const InputIterator<T, Distance>&) {
return (T*)();
} template <class T, class Distance>
inline T* ValueType(const ForwardIterator<T, Distance>&) {
return (T*)();
} template <class T, class Distance>
inline T* ValueType(const BidirectionalIterator<T, Distance>&) {
return (T*)();
} template <class T, class Distance>
inline T* ValueType(const RandomAccessIterator<T, Distance>&) {
return (T*)();
} template <class T>
inline T* ValueType(const T*) { return (T*)(); }
  迭代器是一种抽象的设计概念。他提供一种方法,使之能够依序寻访某个容器所含的各个元素,而又无需暴露该容器的的内部表述方式。迭代器的行为类似指针需要对operator*和operator->进行重载
  智能指针也算是迭代器的一种,原生指针也可以说是迭代器。但是他们不能直接用作迭代器,因为无法获得智能指针所指向的类型,我们使用迭代器的时候很可能会用到迭代器的相应型别

STL_TypeTraits.h

 #pragma once

 struct InputIterator_tag {};
struct OutputIterator_tag {};
struct ForwardIterator_tag : public InputIterator_tag {};
struct BidirectionalIterator_tag : public ForwardIterator_tag {};
struct RandomAccessIterator_tag : public BidirectionalIterator_tag {}; template <class T, class Distance> struct InputIterator {
typedef InputIterator_tag IteratorCategory;
typedef T ValueType;
typedef Distance DifferenceType;
typedef T* Pointer;
typedef T& Reference;
}; struct OutputIterator {
typedef OutputIterator_tag IteratorCategory;
typedef void ValueType;
typedef void DifferenceType;
typedef void Pointer;
typedef void Reference;
}; template <class T, class Distance> struct ForwardIterator {
typedef ForwardIterator_tag IteratorCategory;
typedef T ValueType;
typedef Distance DifferenceType;
typedef T* Pointer;
typedef T& Reference;
}; template <class T, class Distance> struct BidirectionalIterator {
typedef BidirectionalIterator_tag IteratorCategory;
typedef T ValueType;
typedef Distance DifferenceType;
typedef T* Pointer;
typedef T& Reference;
}; template <class T, class Distance> struct RandomAccessIterator {
typedef RandomAccessIterator_tag IteratorCategory;
typedef T ValueType;
typedef Distance DifferenceType;
typedef T* Pointer;
typedef T& Reference;
}; template <class Category, class T, class Distance = size_t, class Pointer = T*, class Reference = T&>
struct Iterator {
typedef Category IteratorCategory;
typedef T ValueType;
typedef Distance DifferenceType;
typedef Pointer Pointer;
typedef Reference Reference;
}; template <class Iterator>
struct IteratorTraits
{
typedef typename Iterator::IteratorCategory IteratorCategory;
typedef typename Iterator::ValueType ValueType;
typedef typename Iterator::DifferenceType DifferenceType;
typedef typename Iterator::Pointer Pointer;
typedef typename Iterator::Reference Reference;
};//ÀàÐÍÝÍÈ¡»ú template <class T>
struct IteratorTraits<T*>
{
typedef RandomAccessIterator_tag IteratorCategory;
typedef T ValueType;
typedef ptrdiff_t DifferenceType;
typedef T* Pointer;
typedef T& Reference;
}; template<class InputIterator>
int Distance(InputIterator first, InputIterator last)
{
return _Distance(first, last, IteratorTraits<InputIterator>::IteratorCategory());
} template<class InputIterator>
int _Distance(InputIterator first, InputIterator last, ForwardIterator_tag)
{
int count = ;
while (first != last)
{
count++;
first++;
}
return count;
} template<class InputIterator>
int _Distance(InputIterator first, InputIterator last, RandomAccessIterator_tag)
{
return last - first;
} //template <class Iterator>
//inline typename IteratorTraits<Iterator>::DifferenceType*
//DifferenceType(const Iterator&) {
// return static_cast<typename IteratorTraits<Iterator>::DifferenceType*>(0);
//} template <class T, class Distance>
inline T* ValueType(const InputIterator<T, Distance>&) {
return (T*)();
} template <class T, class Distance>
inline T* ValueType(const ForwardIterator<T, Distance>&) {
return (T*)();
} template <class T, class Distance>
inline T* ValueType(const BidirectionalIterator<T, Distance>&) {
return (T*)();
} template <class T, class Distance>
inline T* ValueType(const RandomAccessIterator<T, Distance>&) {
return (T*)();
} template <class T>
inline T* ValueType(const T*) { return (T*)(); }

    类型萃取分为POD类型(基本数据类型)和非POD类型,POD类型有库提供的构造函数,析构函数,拷贝构造等,而非POD类型没有,需要用户自定义这些功能。使用类型萃取是把这两种类型分开,然后对POD类型不用处理对非POD类型自定义实现功能,从而达到代码重用。

    

参考:http://www.cnblogs.com/lenomirei/p/5379289.html  STL的迭代器和类型萃取

     http://blog.csdn.net/lf_2016/article/details/53511648  揭秘——STL空间配置器

模拟实现STL库的更多相关文章

  1. [转] C++的STL库,vector sort排序时间复杂度 及常见容器比较

    http://www.169it.com/article/3215620760.html http://www.cnblogs.com/sharpfeng/archive/2012/09/18/269 ...

  2. 使用STL库sort函数对vector进行排序

    使用STL库sort函数对vector进行排序,vector的内容为对象的指针,而不是对象. 代码如下 #include <stdio.h> #include <vector> ...

  3. 【实习记】2014-08-15文档太少看着源码用cgicc+stl库之模板谓词函数对象

        总结1: 今天找到了昨天scanf的问题答案,scanf与printf一样的神奇而复杂,稍不留神,就会被坑.scanf函数在读入非空白符分割的多个字符串的解决方法是这个:/* 以 | 分割 * ...

  4. STL库list::sort()实现深度解析

    原创,转载请注明出处:STL库list::sort()实现深度解析 list模板的定义以及一些基本成员函数的实现这里我就不赘述了,还不清楚的同学可以到网上查找相关资料或者直接查看侯捷翻译的<ST ...

  5. STL库中string类内存布局的探究

    在STL中有着一个类就是string类,他的内存布局和存储机制究竟是怎么样的呢? 这就是建立好的string 可以看出,图中用黄色框框标注的部分就是主要区域 我们用来给string对象进行初始化的字符 ...

  6. 关于STL库中的max min swap

    嗯...   不得不说c++中的STL库是一个神奇的东西   可以使你的代码显得更加简洁....   今天就只讲STL中的三个鬼畜:   max       min       swap   具体操作 ...

  7. 【uva 1152】4 Values Whose Sum is Zero(算法效率--中途相遇法+Hash或STL库)

    题意:给定4个N元素几个A,B,C,D,要求分别从中选取一个元素a,b,c,d使得a+b+c+d=0.问有多少种选法.(N≤4000,D≤2^28) 解法:首先我们从最直接最暴力的方法开始思考:四重循 ...

  8. vscode无法运行和调试使用了部分stl库的程序(无法定位程序输入点__gxx_personality_v0的一个解决方法)

    一.起因 vscode 不能运行带有部分 stl 库的程序,编译不会报错,运行也不会报错但是也没有结果,调试的话会有下图中报错,如果没有string或者vector一切正常. 二.分析  cmd 中运 ...

  9. c++中STL库简介及使用说明

    作为C++标准不可缺少的一部分,STL应该是渗透在C++程序的角角落落里的.STL不是实验室里的宠儿,也不是程序员桌上的摆设,她的激动人心并非昙花一现.本教程旨在传播和普及STL的基础知识,若能借此机 ...

随机推荐

  1. pycharm打开脚本报错Gtk-Message: Failed to load module "canberra-gtk-module"

    解决方法 sudo apt-get install libcanberra-gtk-module

  2. C++11之nullptr

    [C++11空指针] 1.NULL的问题 class Test { public: void TestWork(int index) { std::cout << "TestWo ...

  3. Android中Activity的四种启动方式

    谈到Activity的启动方式必须要说的是数据结构中的栈.栈是一种只能从一端进入存储数据的线性表,它以先进后出的原则存储数据,先进入的数据压入栈底,后进入的数据在栈顶.需要读取数据的时候就需要从顶部开 ...

  4. 跨版本mysqldump恢复报错Errno1449

    已经有一套主从mysql,新增两个slave主库Server version: 5.6.22-log MySQL Community Server (GPL)旧从库Server version: 5. ...

  5. (转)Docker镜像中的base镜像理解

    base 镜像有两层含义: 不依赖其他镜像,从 scratch 构建. 其他镜像可以之为基础进行扩展. 所以,能称作 base 镜像的通常都是各种 Linux 发行版的 Docker 镜像,比如 Ub ...

  6. [C++] Lvalue and Rvalue Reference

    Lvalue and Rvalue Reference int a = 10;// a is in stack int& ra = a; // 左值引用 int* && pa ...

  7. js运算浮点数

    在js中做小数:9.3+0.3会发现,得到的结果并不是9.6,而是9.600000000000001.这是为什么? Javascript采用了IEEE-745浮点数表示法,这是一种二进制表示法,可以精 ...

  8. (转)unordered_map与map的对比(C++11新特性)

    unordered_map和map类似,都是存储的key-value的值,可以通过key快速索引到value.不同的是unordered_map不会根据key的大小进行排序, 存储时是根据key的ha ...

  9. jQuary总结5:传递一个dom对象

    1 传递一个dom对象 //html <div></div> <p id="p"></p> //js var p = documen ...

  10. 弱网测试弱网测试—Network-Emulator-Toolkit

    原文:https://blog.csdn.net/no1mwb/article/details/53638681