STL源码解析之vector自实现

1.vector实现框架2.空间配置器空间配置器方面的内容在之前的博客已进行详细说明,查看->STL空间配置器解析和实现.3.内存基本处理工具(1)对象构造(2)Destroy(

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

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

1. vector实现框架

  STL源码解析之vector自实现

2. 空间配置器

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

3. 内存基本处理工具

  (1)对象构造

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

  (3)迭代器范围赋值

  (4)迭代器范围拷贝

STL源码解析之vector自实现
STL源码解析之vector自实现

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 = 0; 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;
}

View Code

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函数的就可以根据其做相应的处理

STL源码解析之vector自实现
STL源码解析之vector自实现

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

View Code

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 - 1));
        ++Finish;
        T x_copy = value;
        //copy_backward(position, Finish - 2, Finish - 1);
        *position = x_copy;
    }
    else
    {
        // 已无备用空间
        size_type nOldSize = Size();
        size_type nNewSize = (nOldSize == 0) ? 1 : 2 * 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 + 1 != Finish)
    {
        copy(pos + 1, 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 = 0; 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. 全部实现

STL源码解析之vector自实现
STL源码解析之vector自实现

#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 + 1 != Finish)
        {
            copy(pos + 1, 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 = 0; 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 - 1));
            ++Finish;
            T x_copy = value;
            //copy_backward(position, Finish - 2, Finish - 1);
            *position = x_copy;
        }
        else
        {
            // 已无备用空间
            size_type nOldSize = Size();
            size_type nNewSize = (nOldSize == 0) ? 1 : 2 * 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 = 0; 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源码解析之vector自实现
STL源码解析之vector自实现

// 完全解析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 = 0);
    static void SetCallBackHandle(CallBackFunc cb);

private:
    static void* ReAllocate(size_t nSize);
    static void* ReAllocate(void *p, size_t nSize);
};

enum {ALIGN = 8};  // 小型区块的上调边界
enum {MAX_BYTES = 128}; // 小型区块的上限
enum {FREELISTNUM = MAX_BYTES/ALIGN}; // free-lists个数

// 空闲内存链表结构
union FreeList
{
    union FreeList *pFreeList;
    char client_data[1];
};

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

STL源码解析之vector自实现
STL源码解析之vector自实现

#pragma once

#include "alloc_define.h"
template<typename T, typename Alloc = SelfAlloc>
class CSimpleAlloc
{
public:
    static T* Allocate(size_t n)
    {
        if (n == 0)
        {
            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 != 0)
        {
            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(4, 5);    vect1.Print();    cout << "Vector()--Push()--Pop测试:" << endl;    Vector<int> vect2;    vect2.Push(1);    vect2.Push(2);    vect2.Push(3);    vect2.Push(4);    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(2, 88);    vect2.Print();    vect2.Resize(8, 66);    vect2.Print();}

STL源码解析之vector自实现

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/120126.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 回声状态网络基础知识_肝血管瘤内回声成网络样

    回声状态网络基础知识_肝血管瘤内回声成网络样http://jlearning.cn/2017/05/29/ESN-basic-tutorial/最近在看回声状态网络(EchoStateNetwork)的内容,注意到中文搜索引擎搜不到关于有关EchoStateNetwork通俗的讲解,打算写一下关于ESN的一个基本教程。本文先用一小段简单介绍ESN是什么,然后用公式来表示这种网络,并说明他的优缺点,最后用一个可执行的简单例子来演示…

    2022年10月21日
    2
  • 图的两种遍历方式

    图的两种遍历方式遍历是指从某个节点出发,按照一定的的搜索路线,依次访问对数据结构中的全部节点,且每个节点仅访问一次。在二叉树基础中,介绍了对于树的遍历。树的遍历是指从根节点出发,按照一定的访问规则,依次访问树的每个节点信息。树的遍历过程,根据访问规则的不同主要分为四种遍历方式:(1)先序遍历(2)中序遍历(3)后序遍历(4)层次遍历类似的,图的遍历是指,从给定图中任意指定的顶点(称为初始点…

    2022年6月14日
    31
  • gcc命令的常用选项_curl常用命令及参数

    gcc命令的常用选项_curl常用命令及参数gcc是GUNC和C++编译器,我们通常使用GCC时,编译器会依次做如下工作:preprocess(预处理),compilation(编译),assembly(汇编),link(链接)。gcc提供了一些选项参数能够让编译器停在某个过程(如编译过程)。

    2022年10月13日
    3
  • CreateThread WaitForMultipleObjects[通俗易懂]

    CreateThread WaitForMultipleObjects[通俗易懂]//最简单的创建多线程实例#include#include//子线程函数DWORDWINAPIThreadFun(LPVOIDpM){printf(“子线程的线程ID号为:%d\n子线程输出HelloWorld\n”,GetCurrentThreadId());return0;}//主函数,所谓主函数其实就是主线程执行的函数。intmain

    2022年7月27日
    11
  • 单片机led点阵显示程序_LED点阵

    单片机led点阵显示程序_LED点阵单片机LED点阵一、简述     使用8×8LED点阵显示汉字。向上滚动"中华"两个汉字。   文件打包:链接:https://pan.baidu.com/s/1oHSAIY6qVA7qFFWUvMvJEA密码:snyg二、效果三、工程文件结构1、Keil工程2、仿真电路图四、代码88led.c文件#include&lt;reg51.h&gt;#defineuintunsigne…

    2025年8月19日
    2
  • 双线性插值(Bilinear Interpol)原理及应用

    双线性插值(Bilinear Interpol)原理及应用在很多神经网络上采样过程中会用到双线性插值,其为基础的图像resize操作。以前一直没时间仔细研究,今天探究并记录一下原理和自己的理解。一、什么是插值插值指两个方面:一是在数学上,在离散数据的基础上补插连续函数,使得这条连续曲线通过全部给定的离散数据点;二是在图像处理上面,是利用已知邻近像素点的灰度值或RGB中的三色值产生未知像素点的灰度值或RGB三色值,目的是由原始图像再生出具有更高分辨率的图像。通俗一点理解就是已知推导未知,从而强化图像,具体效果如图1所示。…

    2022年6月1日
    69

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号