最近仔细阅读了下侯捷老师的《STL源码剖析》的前三章内容:空间配置器、迭代器、traits技术,为了加强理解和掌握,特参照源码自实现Vector,以下对相关重点知识进行说明。

1. vector实现框架

  

2. 空间配置器

  空间配置器方面的内容在之前的博客已进行详细说明,查看->STL空间配置器解析和实现.

3. 内存基本处理工具

  (1)对象构造

  (2)Destroy()函数的泛化和特化版本实现,主要体现对象T是否包含trivial construct

  (3)迭代器范围赋值

  (4)迭代器范围拷贝

template<class T1, class T2>
void Construct(T1* p, const T2& value)
{
new (p) T1(value); // placement new;调用T1::T1(value)
} template<class T>
void Destroy(T* p)
{
p->~T();
p = NULL;
} template<class ForwardIterator>
void Destroy(ForwardIterator first, ForwardIterator last)
{
ForwardIterator iter = first;
while (iter != last)
{
typedef typename TRAITS_DEFINE::iterator_traits<ForwardIterator>::value_type T;
cout << typeid(T).name();
T p = (T)*iter;
Destroy(&p);
iter++;
}
} template<class ForwardIterator>
void Destroy(ForwardIterator first, ForwardIterator last, TRAITS_DEFINE::__true_type)
{
;
} template<class ForwardIterator>
void Destroy(ForwardIterator first, ForwardIterator last, TRAITS_DEFINE::__false_type)
{
for (; first<last; first++)
{
Destroy(&*first)
}
} template<class ForwardIterator, class T>
void Destroy(ForwardIterator first, ForwardIterator last, T*)
{
typedef typename TRAITS_DEFINE::__type_traits<T>::has_trivial_destructor trivial_destructor;
Destroy(first, last, trivial_destructor());
}
template<class OutputIterator>
OutputIterator uninitialized_fill_n_ex(OutputIterator iter, const size_type& nSize, const T& nValue)
{
for (size_t i = ; i < nSize; i++)
{
*iter++ = nValue;
} return iter;
} void Fill_Initialize(const size_type& nSize, const T& nValue)
{
Iterator iter = data_allocator::Allocate(nSize);
uninitialized_fill_n_ex(iter, nSize, nValue); Start = iter;
Finish = Start + nSize;
EndOfStorage = Finish;
} template<class InputIterator, class OutputIterator>
OutputIterator uninitialzed_copy_ex(InputIterator first, InputIterator last, OutputIterator dest)
{
for (; first != last; first++,dest++)
{
*dest = *first;
} return dest;
}

4. iterator_traites和type_traits

  类型萃取实现的关键计数在于“模版特例化”,通过class template partial specialization的作用,不论是原生指针或class-type iterators,都可以让外界方便地取其相应类别

  原生指针不是class type,如果不是class type就无法为它定义内嵌型别。但模板特例化解决了该问题

  template<class T>

  class C{...};    // 这个泛化版本允许(接受)T为任何型别

  template<class T>

  class C<T*>{...}; // 这个特化版本仅适用于“T为原生指针”的情况

  type_traits类型萃取,判断T类型中是否含有trivial construct,这样在destroy函数的就可以根据其做相应的处理

namespace TRAITS_DEFINE
{
template<class T>
struct iterator_traits
{
typedef T value_type;
}; template<class T>
struct iterator_traits<T *>
{
typedef T value_type;
}; struct __true_type{};
struct __false_type{};
template<class type>
struct __type_traits
{
typedef __true_type this_dummy_must_be_first;
typedef __false_type has_trivial_default_constructor;
typedef __false_type has_trivial_copy_constructor;
typedef __false_type has_trivial_assignment_operator;
typedef __false_type has_trivial_destructor;
typedef __false_type is_POD_type;
}; template<>
struct __type_traits<int>
{
typedef __true_type this_dummy_must_be_first;
typedef __true_type has_trivial_default_constructor;
typedef __true_type has_trivial_copy_constructor;
typedef __true_type has_trivial_assignment_operator;
typedef __true_type has_trivial_destructor;
typedef __true_type is_POD_type;
};
}

5. vector代码实现

5.1. 构造

typedef T& Reference;
typedef T* Iterator;
typedef T value_type;
typedef size_t size_type;
typedef CSimpleAlloc<value_type> data_allocator; // 自定义空间配置器 Iterator Start;
Iterator Finish;
Iterator EndOfStorage;

Vector():Start(NULL), Finish(NULL),EndOfStorage(NULL){
cout << "Vector()" << endl;
}
Vector(const size_type& nSize, const T& nValue)
{
  Fill_Initialize(nSize, nValue);
}
explicit Vector(const size_type& nSize)
{
  Fill_Initialize(nSize, T());
}

void Fill_Initialize(const size_type& nSize, const T& nValue)
{
Iterator iter = data_allocator::Allocate(nSize);
uninitialized_fill_n_ex(iter, nSize, nValue); Start = iter;
Finish = Start + nSize;
EndOfStorage = Finish;
}

5.2. 析构 

void Deallocate()
{
if (Start)
{
data_allocator::Deallocate(Start, EndOfStorage-Start);
}
}

~Vector()
{
  Destroy(Start, Finish);
  Deallocate();
}

5.3. Push

void Push(const T& Value)
{
if (Finish != EndOfStorage)
{
Construct(Finish, Value); // 全局函数
++Finish;
}
else
{
// 容器已满,需扩容
Insert_Aux(End(), Value);
}
}
void Insert_Aux(Iterator position, const T& value)
{
if (Finish != EndOfStorage)
{
// 还有备用空间可用
Construct(Finish, *(Finish - ));
++Finish;
T x_copy = value;
//copy_backward(position, Finish - 2, Finish - 1);
*position = x_copy;
}
else
{
// 已无备用空间
size_type nOldSize = Size();
size_type nNewSize = (nOldSize == ) ? : * nOldSize;
Iterator NewStart = data_allocator::Allocate(nNewSize);
Iterator NewFinish = NewStart;
try
{
NewFinish = uninitialzed_copy_ex(Start, position, NewStart);
Construct(NewFinish, value);
NewFinish++;
}
catch (...)
{
Destroy(NewStart, NewFinish);
data_allocator::Deallocate(NewStart, nNewSize);
throw;
} Destroy(Begin(),End());
data_allocator::Deallocate(Start, EndOfStorage - Start); Start = NewStart;
Finish = NewFinish;
EndOfStorage = Start + nNewSize;
}
}

5.4. Pop_Back

void Pop_Back()
{
if (!Empty())
{
--Finish;
Destroy(Finish);
}
}

5.5. Erase

  Erase方法只能清空元素,但不能释放空间

Iterator Erase(Iterator pos)
{
if (pos + != Finish)
{
copy(pos + , Finish, pos);
}
--Finish;
destroy(Finish);
return pos;
}
Iterator Erase(Iterator first, Iterator last)
{
Iterator iter = uninitialzed_copy_ex(last, Finish, first);
Destroy(iter, Finish);
Finish = Finish - (last - first);
return first;
}

5.6. Resize

void Resize(size_type new_size, const T& x) {
//如果新空间大小 小于size 就裁去多余的 如果新空间大于size那么就将这些插入.
if (new_size < Size())
Erase(Begin() + new_size, End());
else
{
Iterator NewStart = data_allocator::Allocate(new_size);
Iterator NewFinish = NewStart;
try
{
NewFinish = uninitialzed_copy_ex(Start, Finish, NewStart);
for (size_t i = ; i < (new_size-Size()); i++)
{
*NewFinish++ = x; }
}
catch (...)
{
Destroy(NewStart, NewFinish);
data_allocator::Deallocate(NewStart, new_size);
throw;
} Destroy(Begin(), End());
data_allocator::Deallocate(Start, EndOfStorage - Start); Start = NewStart;
Finish = NewFinish;
EndOfStorage = Start + new_size;
}
}

5.7. 全部实现

#pragma once
#include "simple_alloc.h"
#include <iostream>
#include<memory>
using namespace std; /*
Construct和Destroy实现
*/
namespace TRAITS_DEFINE
{
template<class T>
struct iterator_traits
{
typedef T value_type;
}; template<class T>
struct iterator_traits<T *>
{
typedef T value_type;
}; struct __true_type{};
struct __false_type{};
template<class type>
struct __type_traits
{
typedef __true_type this_dummy_must_be_first;
typedef __false_type has_trivial_default_constructor;
typedef __false_type has_trivial_copy_constructor;
typedef __false_type has_trivial_assignment_operator;
typedef __false_type has_trivial_destructor;
typedef __false_type is_POD_type;
}; template<>
struct __type_traits<int>
{
typedef __true_type this_dummy_must_be_first;
typedef __true_type has_trivial_default_constructor;
typedef __true_type has_trivial_copy_constructor;
typedef __true_type has_trivial_assignment_operator;
typedef __true_type has_trivial_destructor;
typedef __true_type is_POD_type;
};
} // 内存管理工具
template<class T1, class T2>
void Construct(T1* p, const T2& value)
{
new (p) T1(value); // placement new;调用T1::T1(value)
} template<class T>
void Destroy(T* p)
{
p->~T();
p = NULL;
} template<class ForwardIterator>
void Destroy(ForwardIterator first, ForwardIterator last)
{
ForwardIterator iter = first;
while (iter != last)
{
typedef typename TRAITS_DEFINE::iterator_traits<ForwardIterator>::value_type T;
cout << typeid(T).name();
T p = (T)*iter;
Destroy(&p);
iter++;
}
} template<class ForwardIterator>
void Destroy(ForwardIterator first, ForwardIterator last, TRAITS_DEFINE::__true_type)
{
;
} template<class ForwardIterator>
void Destroy(ForwardIterator first, ForwardIterator last, TRAITS_DEFINE::__false_type)
{
for (; first<last; first++)
{
Destroy(&*first)
}
} template<class ForwardIterator, class T>
void Destroy(ForwardIterator first, ForwardIterator last, T*)
{
typedef typename TRAITS_DEFINE::__type_traits<T>::has_trivial_destructor trivial_destructor;
Destroy(first, last, trivial_destructor());
} /*
* 实现vector
* vector基本操作:构造、resize、erase、push、pop
*/
template <typename T>
class Vector
{
public:
typedef T& Reference;
typedef T* Iterator;
typedef T value_type;
typedef size_t size_type;
typedef CSimpleAlloc<value_type> data_allocator; // 自定义空间配置器 Iterator Start;
Iterator Finish;
Iterator EndOfStorage; public:
Vector():Start(NULL), Finish(NULL),EndOfStorage(NULL){
cout << "Vector()" << endl;
}
Vector(const size_type& nSize, const T& nValue)
{
Fill_Initialize(nSize, nValue);
}
explicit Vector(const size_type& nSize)
{
Fill_Initialize(nSize, T());
}
~Vector()
{
Destroy(Start, Finish);
Deallocate();
}
Iterator Begin(){return Start;}
Iterator End(){return Finish;}
size_type Size() const { return size_type(Finish - Start); }
size_type Capacity() const { return size_type(EndOfStorage - Start); }
bool Empty() { return Begin() == End(); }
Reference operator[](const size_type& nIndex)
{
return *(start + n);
} Reference Front(){ return *Start; }
Reference Back(){ return *(--Finish); } void Push(const T& Value)
{
if (Finish != EndOfStorage)
{
Construct(Finish, Value); // 全局函数
++Finish;
}
else
{
// 容器已满,需扩容
Insert_Aux(End(), Value);
} }
void Pop_Back()
{
if (!Empty())
{
--Finish;
Destroy(Finish);
}
} void Print()
{
cout << "打印vector所有元素: ";
Iterator iter = Start;
while (iter != Finish)
{
cout << *iter << " ";
iter++;
}
cout << endl;
} Iterator Erase(Iterator pos)
{
if (pos + != Finish)
{
copy(pos + , Finish, pos);
}
--Finish;
destroy(Finish);
return pos;
}
Iterator Erase(Iterator first, Iterator last)
{
Iterator iter = uninitialzed_copy_ex(last, Finish, first);
Destroy(iter, Finish);
Finish = Finish - (last - first);
return first;
} void Resize(size_type new_size, const T& x) {
//如果新空间大小 小于size 就裁去多余的 如果新空间大于size那么就将这些插入.
if (new_size < Size())
Erase(Begin() + new_size, End());
else
{
Iterator NewStart = data_allocator::Allocate(new_size);
Iterator NewFinish = NewStart;
try
{
NewFinish = uninitialzed_copy_ex(Start, Finish, NewStart);
for (size_t i = ; i < (new_size-Size()); i++)
{
*NewFinish++ = x; }
}
catch (...)
{
Destroy(NewStart, NewFinish);
data_allocator::Deallocate(NewStart, new_size);
throw;
} Destroy(Begin(), End());
data_allocator::Deallocate(Start, EndOfStorage - Start); Start = NewStart;
Finish = NewFinish;
EndOfStorage = Start + new_size;
}
} void Clear()
{
Erase(Start, Finish);
}
private: void Deallocate()
{
if (Start)
{
data_allocator::Deallocate(Start, EndOfStorage-Start);
}
}
void Insert_Aux(Iterator position, const T& value)
{
if (Finish != EndOfStorage)
{
// 还有备用空间可用
Construct(Finish, *(Finish - ));
++Finish;
T x_copy = value;
//copy_backward(position, Finish - 2, Finish - 1);
*position = x_copy;
}
else
{
// 已无备用空间
size_type nOldSize = Size();
size_type nNewSize = (nOldSize == ) ? : * nOldSize;
Iterator NewStart = data_allocator::Allocate(nNewSize);
Iterator NewFinish = NewStart;
try
{
NewFinish = uninitialzed_copy_ex(Start, position, NewStart);
Construct(NewFinish, value);
NewFinish++;
}
catch (...)
{
Destroy(NewStart, NewFinish);
data_allocator::Deallocate(NewStart, nNewSize);
throw;
} Destroy(Begin(),End());
data_allocator::Deallocate(Start, EndOfStorage - Start); Start = NewStart;
Finish = NewFinish;
EndOfStorage = Start + nNewSize;
}
} // 申请并填充内存
template<class OutputIterator>
OutputIterator uninitialized_fill_n_ex(OutputIterator iter, const size_type& nSize, const T& nValue)
{
for (size_t i = ; i < nSize; i++)
{
*iter++ = nValue;
} return iter;
} void Fill_Initialize(const size_type& nSize, const T& nValue)
{
Iterator iter = data_allocator::Allocate(nSize);
uninitialized_fill_n_ex(iter, nSize, nValue); Start = iter;
Finish = Start + nSize;
EndOfStorage = Finish;
} template<class InputIterator, class OutputIterator>
OutputIterator uninitialzed_copy_ex(InputIterator first, InputIterator last, OutputIterator dest)
{
for (; first != last; first++,dest++)
{
*dest = *first;
} return dest;
}
};

vector_define.h

// 完全解析STL空间配置器
/***** 一级配置区 ****************************/
// 1. 采用mallo/relloc/free申请和释放内存
// 2. 处理内存申请失败的处理
// (1)设置set_new_handle,若为NULL抛出__THROW_BAD_ALLOC;
// (2)尝试重复申请
/**********************************************/
#pragma once class CFirstLevelAlloc;
class CSecondLevelAlloc; #ifdef _CHUNK_ALLOC
typedef CFirstLevelAlloc SelfAlloc;
#else
typedef CSecondLevelAlloc SelfAlloc;
#endif typedef void(*CallBackFunc)();
class CFirstLevelAlloc
{
public:
CFirstLevelAlloc(); static CallBackFunc m_CallBackFunc;
static void* Allocate(size_t nSize);
static void* Allocate(void *p, size_t nSize);
static void Deallocate(void *p, size_t nSize = );
static void SetCallBackHandle(CallBackFunc cb); private:
static void* ReAllocate(size_t nSize);
static void* ReAllocate(void *p, size_t nSize);
}; enum {ALIGN = }; // 小型区块的上调边界
enum {MAX_BYTES = }; // 小型区块的上限
enum {FREELISTNUM = MAX_BYTES/ALIGN}; // free-lists个数 // 空闲内存链表结构
union FreeList
{
union FreeList *pFreeList;
char client_data[];
}; class CSecondLevelAlloc
{
public:
CSecondLevelAlloc();
static void* Allocate(size_t nSize);
static void Deallocate(void *p, size_t nSize);
static void SetCallBackHandle(CallBackFunc cb); private:
static size_t FreeListIndex(int nBytes); // 根据区块大小得到freelist索引
static size_t Round_Up(int nBytes); // 将bytes按内存对齐上调至ALIGN的倍数
static char *ChunkAlloc(size_t nSize, int& nObjs);
static void* Refill(size_t nSize); private:
static FreeList *m_pFreeList[FREELISTNUM];
static char *m_pStartFree;
static char *m_pEndFree;
static size_t m_nHeapSize;
};

alloc_define.h

#pragma once

#include "alloc_define.h"
template<typename T, typename Alloc = SelfAlloc>
class CSimpleAlloc
{
public:
static T* Allocate(size_t n)
{
if (n == )
{
return NULL;
}
return (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));
} static void SetCallBackHandle(CallBackFunc cb)
{
Alloc::SetCallBackHandle(cb);
}
};

simple_alloc.h

5.8. 测试

#include "stdio.h"

#include "vector_define.h"

#include<vector>
using namespace std; void main()
{
cout << "Vector(const size_type& nSize, const T& nValue)测试:" << endl;
Vector<int> vect1(, );
vect1.Print(); cout << "Vector()--Push()--Pop测试:" << endl;
Vector<int> vect2;
vect2.Push();
vect2.Push();
vect2.Push();
vect2.Push();
vect2.Print();
vect2.Pop_Back();
vect2.Print(); cout << "Iterator Erase(Iterator first, Iterator last)测试:" << endl;
Vector<int>::Iterator iter1 = vect2.Begin();
Vector<int>::Iterator iter2 = vect2.End();
vect2.Erase(iter1, iter2);
cout << "vect Size:" << vect2.Size() << endl; cout << "void Resize(size_type new_size, const T& x)测试:" << endl;
vect2.Resize(, );
vect2.Print();
vect2.Resize(, );
vect2.Print();
}

STL源码解析之vector自实现的更多相关文章

  1. Java集合类源码解析:Vector

    [学习笔记]转载 Java集合类源码解析:Vector   引言 之前的文章我们学习了一个集合类 ArrayList,今天讲它的一个兄弟 Vector.为什么说是它兄弟呢?因为从容器的构造来说,Vec ...

  2. stl源码分析之vector

    上篇简单介绍了gcc4.8提供的几种allocator的实现方法和作用,这是所有stl组件的基础,容器必须通过allocator申请分配内存和释放内存,至于底层是直接分配释放内存还是使用内存池等方法就 ...

  3. 《STL源码剖析》——Vector

    vector vector的源码分为多个文件:vector.<<stl_vector.h>> vector的底层实现是在<<stl_vector.h>> ...

  4. STL源码剖析-vector

    STL(Standard Template Library) C++标准模板库,acm选手一定对它不陌生,除了算法,那几乎是“吃饭的家伙了”.我们使用库函数非常方便,且非常高效(相对于自己实现来说). ...

  5. vector源码3(参考STL源码--侯捷):pop_back、erase、clear、insert

    vector源码1(参考STL源码--侯捷) vector源码2(参考STL源码--侯捷):空间分配.push_back vector源码(参考STL源码--侯捷)-----空间分配导致迭代器失效 v ...

  6. vector源码(参考STL源码--侯捷):空间分配导致迭代器失效

    vector源码1(参考STL源码--侯捷) vector源码2(参考STL源码--侯捷) vector源码(参考STL源码--侯捷)-----空间分配导致迭代器失效 vector源码3(参考STL源 ...

  7. vector源码2(参考STL源码--侯捷):空间分配、push_back

    vector源码1(参考STL源码--侯捷) vector源码2(参考STL源码--侯捷) vector源码(参考STL源码--侯捷)-----空间分配导致迭代器失效 vector源码3(参考STL源 ...

  8. vector源码1(参考STL源码--侯捷):源码

    vector源码1(参考STL源码--侯捷) vector源码2(参考STL源码--侯捷) vector源码(参考STL源码--侯捷)-----空间分配导致迭代器失效 vector源码3(参考STL源 ...

  9. Java 集合系列06之 Vector详细介绍(源码解析)和使用示例

    概要 学完ArrayList和LinkedList之后,我们接着学习Vector.学习方式还是和之前一样,先对Vector有个整体认识,然后再学习它的源码:最后再通过实例来学会使用它.第1部分 Vec ...

随机推荐

  1. nodejs fs学习

    在本章的开始,我本来只想写一些关于fs模块的内容,虽然这个模块包含的方法非常的多,但没有想到的是它和我们上一篇文章Node.js Buffer还存在着关联,所以我又把关于Buffer的内容简单的学习下 ...

  2. linux 文本分析工具---awk命令(7/1)

    awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大.简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各 ...

  3. CSS3 3D旋转动画菜单

    在线演示 本地下载

  4. PC平台逆向破解

    ---恢复内容开始--- PC平台逆向破解 实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串. ...

  5. java中泛型的一个小问题

    最近做项目,由于java语法不是非常的熟悉,编写代码过程中不难遇到一些问题: 代码里写了一条这种语句: Map<String, List<String>> configFile ...

  6. C++ 之虚函数的实现原理

    c++的多态使用虚函数实现,通过“晚绑定”,使程序在运行的时候,根据对象的类型去执行对应的虚函数. C++ 之虚函数的实现原理 带有虚函数的类,编译器会为其额外分配一个虚函数表,里面记录的使虚函数的地 ...

  7. Spring中Value注解的使用

    Spring中Value注解的使用 分类: Spring2014-08-16 17:28 2985人阅读 评论(0) 收藏 举报 有的时候我们定义了Properties文件,并且使用Spring的Pr ...

  8. ThinkPHP3.2添加scws中文分词

    前言 前一段时间,公司网站做站内搜索,只简单针对输入的文字进行搜索,作全匹配检索,搜索出来的内容很少.如何达到模糊搜索,匹配到更多的内容成了需要解决的问题.于是,今天想到可以做分词检索,如何对输入的一 ...

  9. Linux设置中文语言的一种方式

    刚开始接触Linux时,如果对于英语不太好的人来说,看到英语的系统时就有点头晕. 能把Linux系统设置为中文就变得急需了. 有一个最简单的方法就是,在登录时,下面就有一个选择语言的选项. 如图:

  10. AppWidget源码分析---updateAppWidget过程分析

    转[原文] 前面一篇文章,分析了AppWidgetProvider和RemoteView的源码,从中我们可以知道它们的实现原理,AppWidgetProvider是一个BroadcastReceive ...