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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • app store connect

    app store connect1、用开发者账号登录,新建App,其中套装ID和SKU使用的应用的BundleID。2、添加要求的尺寸的应用截图或预览,填写宣传文本、描述、关键词、技术支持网址、营销网址3、填写App的信息、App审核信息(包括登录的账号密码,App审核团队有疑问或需要额外信息时会与其联络的联系人信息)…

    2022年10月20日
    0
  • devtools怎么用_webpack devtool

    devtools怎么用_webpack devtooldevtool配置一、devtool配置1.sourcemap源码地图2.webpack中的sourcemap3.对于开发环境一、devtool配置1.sourcemap源码地图本小节的知识与webpack无关前端发展到现阶段,很多时候都不会直接运行源代码,可能需要对源代码进行合并、压缩、转换等操作,真正运行的是转换后的代码与此同时就给调试带来了困难,因为当运行发生错误的时候,我们更加希望能看到源代码中的错误,而不是转换后代码的错误为了解决这一问题,chrome浏览器率先支持

    2022年10月6日
    0
  • Python 实现毫秒级淘宝抢购脚本

    Python 实现毫秒级淘宝抢购脚本本篇文章主要介绍了Python通过selenium实现毫秒级自动抢购的示例代码,通过扫码登录即可自动完成一系列操作,抢购时间精确至毫秒,可抢加购物车等待时间结算的,也可以抢聚划算的商品。博主不提供任何服务器端程序,也不提供任何收费抢购软件。该文章仅作为学习selenium框架的一个示例代码。该思路可运用到其他任何网站,京东,天猫,淘宝均可使用,且不属于外挂或者软件之类,只属于一个自动化点击工…

    2022年4月28日
    207
  • p6操作教程_pc6视频教学

    p6操作教程_pc6视频教学在开发的过程中,我们经常会遇到由于sql语句书写错误导致的bug,那么如何来解决这种困扰呢?如果方法执行完了可以打印出完整的sql语句,就可以方便我们判断执行的是否正确,所以我们希望有一个可以打印sql语句的插件。p6spy就是一款这样的工具,下面给大家介绍一下p6spy的使用。使用p6spy需要做以下三步:1. 导入jar包:将jar包复制到项目中去,记得要buildpath一下。我用…

    2022年10月5日
    0
  • JVM调优工具总结

    JVM调优工具总结一、jps:虚拟机进程状况工具它可以列出正在运行的虚拟机进程,并显示虚拟机执行主类(MainClass,main()函数所在的类)名称以及正在运行的本地虚拟机唯一ID(LVMID);它是使用率最高的一个JDK命令行工具,因为其他的命令行工具都需要输入查询到的ID来确定要监控的是哪一个虚拟机进程。命令格式:jps[options][hostid]选项作用-q只…

    2022年5月6日
    35
  • 手机APP软件性能测试工具及流程介绍[通俗易懂]

    性能测试(上)性能测试的分类和流程什么是性能测试?性能测试概念:性能测试主要通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试性能测试工具:JmeterLoadrunner性能工具的组成:脚本生成器压力生成器结果分析器压力控制器性能工具工作原理:软件性能测…

    2022年4月11日
    61

发表回复

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

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