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


相关推荐

  • 来谈谈SQL数据库中”简单的”SELECT TOP—可能有你从未注意到的细节

    来谈谈SQL数据库中”简单的”SELECT TOP—可能有你从未注意到的细节首先从博客园的JeromeWong网友说起他提出了一个这样的问题本人写了好几年SQL语句了,从来没注意到这件事情。例如:数据表如下:IDEMPNONAMEAGE126929Jerome

    2022年7月4日
    24
  • Java 初中级程序员如何快速成长?

    Java 初中级程序员如何快速成长?入职后如何快速成长到CTO入职后三个月试用期要做的事三法宝,处理同事关系核心两点,处理好领导关系每件事都是学习的机会主动加班,试用期加班是学习的好机会未通过试用期,如何应对?前三年需要学的技术工作后,千万不要停止学习项目经验如何累积?JAVA高级技术还需要学习哪些?架构师课程如何学习?工作中,快速学习新技术的捷径(重要的是形成体系,而不是钻到某个技术点)…

    2022年6月9日
    21
  • C++学习——c++逗号操作符说明(附加全部运算符优先级)

    C++学习——c++逗号操作符说明(附加全部运算符优先级)逗号表达式又称为“顺序求值运算符”。逗号表达式的一般形式为(表达式1,表达式2,表达式3……表达式n)求解过程是:先求解表达式1,再求解表达式2,…。整个逗号表达式的值是最后一个表达式n的值。例如这里的“i++,p++”,先求i++的值,然后求p++的值,整个表达式的值是p++的运算结果另外、逗号运算符是所有运算符中级别最低的/*****************************…

    2022年8月18日
    3
  • c++入门教程–-6循环语句

    c++入门教程–-6循环语句

    2021年3月12日
    135
  • JS中的prototype[通俗易懂]

    JS中的prototype[通俗易懂]JS中的phototype是JS中比较难理解的一个部分本文基于下面几个知识点:1原型法设计模式在.Net中可以使用clone()来实现原型法原型法的主要思想是,现在有1个类A,我想要创建一个类B,这

    2022年7月1日
    23
  • C语言中函数指针和回调函数的详解「建议收藏」

    C语言中函数指针和回调函数的详解「建议收藏」函数指针:指向函数的指针变量。因此“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。这正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数。如前所述,C在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上是大体一致的。函数指针有两个用途:调用函数和做函数…

    2022年6月22日
    26

发表回复

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

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