STL的框架实现

1、模板的特化

泛化模板 : 对各种不同版本的特殊化处理---->特化;

2、萃取

拿相同的代码提取不同的类型;

3、整个搭建框架如下:

在这里已经不关心空间配置器是如何实现的;

其框架代码如下:

#ifndef _MEMORY_H_
#define _MEMORY_H_

#include"stl_alloc.h"
#include"stl_iterator.h"
#include"type_traits.h"
#include"stl_construct.h"
#include"stl_uninitialized.h"

#endif
////////////////////////////////////////////////////////////////////////////////////

#if 1
#include<iostream>
#include<new>
#include<malloc.h>
using namespace std;
//#define __THROW_BAD_ALLOC   throw   bad_alloc
#define __THROW_BAD_ALLOC  cerr<<"Throw bad alloc, Out Of Memory."<<endl; exit(1)
#elif  !defined  (__THROW_BAD_ALLOC)
#include<iostream.h>
#define __THROW_BAD_ALLOC   cerr<<"out of memory"<<endl; exit(1);
#endif

template<int inst>
class __malloc_alloc_template{
private:
    static void* oom_malloc(size_t);
    static void* oom_realloc(void *, size_t);
    static void(* __malloc_alloc_oom_handler)();

public:
    static void* allocate(size_t n){
        void *result = malloc(n);
        if(0 == result){
            result = oom_malloc(n);
        }
        return result;
    }
    static void   deallocate(void *p, size_t){
        free(p);
    }
    static void* reallocate(void *p, size_t, size_t new_sz){
        void *result = realloc(p, new_sz);
        if(0 == result){
            oom_realloc(p,new_sz);
        }
        return result;
    }
public:
    //set_new_handler(Out_Of_Memory);
    static void(*set_malloc_handler(void(*f)()))(){
        void(*old)() = __malloc_alloc_oom_handler;
        __malloc_alloc_oom_handler = f;
        return old;
    }
};

template<int inst>
void (*__malloc_alloc_template<inst>::__malloc_alloc_oom_handler)() = 0;

template<int inst>
void* __malloc_alloc_template<inst>::oom_malloc(size_t n){
    void *result;
    void(* my_malloc_handler)();

    for(;;){
        my_malloc_handler = __malloc_alloc_oom_handler;
        if(0 == my_malloc_handler){ 
            __THROW_BAD_ALLOC;
        }
        (*my_malloc_handler)();
        result = malloc(n);
        if(result){
            return result;
        }
    }
}

template<int inst>
void* __malloc_alloc_template<inst>::oom_realloc(void *p, size_t n){
    void(*my_malloc_handler)();
    void *result;
    for(;;){
        my_malloc_handler = __malloc_alloc_oom_handler;
        if(0 == my_malloc_handler){
            __THROW_BAD_ALLOC;
        }
        (*my_malloc_handler)();
        result = realloc(p, n);
        if(result){
            return result;
        }
    }
}

typedef __malloc_alloc_template<0> malloc_alloc;

/////////////////////////////////////////////////////////////////////////////////////

enum {__ALIGN = 8};
enum {__MAX_BYTES  = 128};
enum {__NFREELISTS = __MAX_BYTES / __ALIGN};

template<bool threads, int inst>
class __default_alloc_template{
public:
    static void* allocate(size_t n);
    static void  deallocate(void *p, size_t n);
    static void* reallocate(void *p, size_t, size_t new_sz);
private:
    static size_t  ROUND_UP(size_t bytes){
        return (((bytes) + __ALIGN-1) & ~(__ALIGN-1));
    }
private:
    union obj{
        union obj * free_list_link;
        char client_data[1];
    };
private:
    static obj* volatile free_list[__NFREELISTS];
    static size_t FREELIST_INDEX(size_t bytes){
        return ((bytes)+__ALIGN-1) / __ALIGN-1;
    }
private:
    static char *start_free;
    static char *end_free;
    static size_t heap_size;
    static void *refill(size_t n);
    static char* chunk_alloc(size_t size, int &nobjs);
};

template<bool threads, int inst>
char* __default_alloc_template<threads, inst>::start_free = 0;
template<bool threads, int inst>
char* __default_alloc_template<threads, inst>::end_free = 0;
template<bool threads, int inst>
size_t __default_alloc_template<threads, inst>::heap_size = 0;
template<bool threads, int inst>
typename __default_alloc_template<threads, inst>::obj* volatile
__default_alloc_template<threads, inst>::free_list[__NFREELISTS] = 
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

template<bool threads, int inst>
void* __default_alloc_template<threads, inst>::allocate(size_t n){
    obj * volatile *my_free_list;
    obj *result;

    if(n > __MAX_BYTES){
        return malloc_alloc::allocate(n);
    }

    my_free_list = free_list + FREELIST_INDEX(n);
    result = *my_free_list;

    if(result == 0){
        void *r = refill(ROUND_UP(n));
        return r;
    }

    *my_free_list = result->free_list_link;
    return result; 
}

template<bool threads, int inst>
void* __default_alloc_template<threads, inst>::refill(size_t n){
    int nobjs = 20;
    char *chunk = chunk_alloc(n, nobjs);
    obj * volatile *my_free_list;

    obj *result;
    obj *current_obj, *next_obj;
    int i;

    if(1 == nobjs){
        return chunk;
    }

    my_free_list = free_list + FREELIST_INDEX(n);
    result = (obj*)chunk;
    *my_free_list = next_obj = (obj*)(chunk+n);

    for(i=1; ; ++i){
        current_obj = next_obj;
        next_obj = (obj*)((char*)next_obj+n);
        if(nobjs - 1 == i){
            current_obj->free_list_link = 0;
            break;
        }else{
            current_obj->free_list_link = next_obj;
        }
    }
    return result;
}

template<bool threads, int inst>
char* __default_alloc_template<threads, inst>::chunk_alloc(size_t size, int &nobjs){
    char *result;
    size_t total_bytes = size * nobjs;
    size_t bytes_left = end_free - start_free;
    if(bytes_left >= total_bytes){
        result = start_free;
        start_free += total_bytes;
        return result;
    }
    else if(bytes_left >= size){
        nobjs = bytes_left / size;
        total_bytes = size * nobjs;
        result = start_free;
        start_free += total_bytes;
        return result;
    }else{
        size_t bytes_to_get = 2 * total_bytes + ROUND_UP(heap_size >> 4);
        if(bytes_left > 0){
            obj * volatile * my_free_list = free_list + FREELIST_INDEX(bytes_left);
            ((obj*)start_free)->free_list_link = *my_free_list;
            *my_free_list = (obj *)start_free;
        }

        start_free = (char *)malloc(bytes_to_get);
        if(0 == start_free){
            int i;
            obj * volatile *my_free_list, *p;
            for(i=size; i<=__MAX_BYTES; i += __ALIGN){
                my_free_list = free_list + FREELIST_INDEX(i);
                p = *my_free_list;
                if(0 != p){
                    *my_free_list = p->free_list_link;
                    start_free = (char *)p;
                    end_free = start_free + i;
                    return chunk_alloc(size, nobjs);
                }
            }
            end_free = 0;
            start_free = (char *)malloc_alloc::allocate(bytes_to_get);
        }

        heap_size  += bytes_to_get;
        end_free = start_free + bytes_to_get;
        return chunk_alloc(size, nobjs);
    }
}

/////////////////////////////////////////////////////////////////////////////////
#ifdef __USE_MALLOC
typedef malloc_alloc  alloc;
#else
typedef __default_alloc_template<0,0> alloc;
#endif

template<class T, class Alloc>
class simple_alloc{ 
public:
    static T* allocate(size_t n){
        return 0==n ? 0 : (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(0!=n) Alloc::deallocate(p, n*sizeof(T));
    }
    static void deallocate(T *p){
        Alloc::deallocate(p,sizeof(T));
    }
};
//////////////////////////////////////////////////////////////////////////////////////////
#ifndef __STL_CONFIG_H
#define __STL_CONFIG_H

//#define __USE_MALLOC

#endif

//////////////////////////////////////////////////////////////////////////////////////////

#ifndef __STL_CONSTRUCT_H
#define __STL_CONSTRUCT_H

template <class T1, class T2>
void construct(T1* p, const T2& value){
      new (p) T1(value);
}

#endif
////////////////////////////////////////////////////////////////////////////////////////
#ifndef __STL_ITERATOR_H
#define __STL_ITERATOR_H

template <class T>
T* value_type(const T*){
    return (T*)(0); 
}

#endif
////////////////////////////////////////////////////////////////////////////////////////
#ifndef __STL_UNINITIALIZED_H
#define __STL_UNINITIALIZED_H

template<class ForwardIterator, class Size, class T>
ForwardIterator _uninitialized_fill_n_aux(ForwardIterator first, Size n, 
                                                const T &x, _true_type){
    cout<<"yyyyyyyyyyy"<<endl;
    return fill_n(first, n, x);
}

template<class ForwardIterator, class Size, class T>
ForwardIterator _uninitialized_fill_n_aux(ForwardIterator first, Size n, 
                                            const T &x, _false_type){
    ForwardIterator cur = first;
    for(; n>0; --n, ++cur){
        cout<<"xxxxxxxxxxxx"<<endl;
        construct( &*cur, x); //construct(cur, x);
    }
    return cur;
}

template<class ForwardIterator, class Size, class T, class T1>
ForwardIterator _uninitialized_fill_n(ForwardIterator first, Size n, const T &x,  T1*){
    //typedef _false_type  is_POD;
    typedef typename _type_traits<T1>::is_POD_type   is_POD;
    //return _uninitialized_fill_n(first, n, x, _false_type());
    return _uninitialized_fill_n_aux(first, n, x, is_POD());
}

template<class ForwardIterator, class Size, class T>
ForwardIterator uninitialized_fill_n(ForwardIterator first, Size n, const T &x){
    return _uninitialized_fill_n(first, n, x, value_type(first));
}

#endif
////////////////////////////////////////////////////////////////////////////////////////
#ifndef __STL_VECTOR_H
#define __STL_VECTOR_H

template<class T, class Alloc=alloc>
class vector{
public:
    typedef T           value_type;
    typedef value_type* pointer;
    typedef value_type* iterator;
    typedef value_type& reference;
    typedef size_t      size_type;
    typedef ptrdiff_t   difference_type;
public:
    vector() : start(0), finish(0), end_of_storage(0){}
    vector(size_type n){
        fill_initialize(n, T());
    }
protected:
    void fill_initialize(size_type n, const T &value){
        start = allocate_and_fill(n, value);
        finish = start + n;
        end_of_storage = finish;
    }
    iterator allocate_and_fill(size_type n, const T &x){
        iterator result = data_allocator::allocate(n);
        uninitialized_fill_n(result, n, x);
        return result;
    }
protected:
    typedef simple_alloc<value_type, Alloc> data_allocator;
    iterator start;
    iterator finish;
    iterator end_of_storage;
};

#endif
////////////////////////////////////////////////////////////////////////////////////////
#ifndef __TYPE_TRAITS_H
#define __TYPE_TRAITS_H

//

struct _true_type {};
struct _false_type{};

template <class type>
struct _type_traits { 
    typedef _true_type     this_dummy_member_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    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;
};

#endif
///////////////////////////////////////////////////////////////////////////////////////
#ifndef _VECTOR_H_
#define _VECTOR_H_

#include"memory.h"
#include"stl_vector.h"

#endif
///////////////////////////////////////////////////////////////////////////////////////

测试代码

#include<iostream>
#include<stdlib.h>
#include"vector.h"
using namespace std;

class Test{};

int main(){
    vector<Test> v(10);  //开辟了10个元素的空间;
    return 0;

测试结果

4、分析

  (1)、vector的空间灵活性更高;

    (2)、POD:也就是标量型别,也就是传统的型别,采取最保险安全的做法,调用构造函数;否则的话,就是调用系统的,基本类型就是true;

    (3)、空构造了2个类型,针对不同萃取得到其_false_type或_true_type ; 就可以调用不同的函数,进行空间的分配,存在效率上的差异!!!

    _true_type:将调用系统的填充函数,效率比较高.

    (4)、容器、算法单独好实现,关键是通用性,模板是一种很好的解决方案,真正关键之处还在 : 迭代器的实现;

    (5)、空间配置器负责分配、回收空间,只有一个;迭代器针对不同的容器有不同的实现方法!!!

时间: 2024-11-15 01:07:02

STL的框架实现的相关文章

C++ STL标准入门

C++:STL标准入门汇总 第一部分:(参考百度百科) 一.STL简介 STL(Standard Template Library,标准模板库)是惠普实验室开发的一系列软件的统称.它是由Alexander Stepanov.Meng Lee和David R Musser在惠普实验室工作时所开发出来 的.现在虽说它主要出现在C++中,但在被引入C++之前该技术就已经存在了很长的一段时间. STL的代码从广义上讲分为三类:algorithm(算法).container(容器)和iterator(迭代

STL源码剖析之组件

本篇文章开始,进行STL源码剖析的一些知识点,后续系列笔记全是参照<STL源码剖析>进行学习记录的 STL在现在的大部分项目中,实用性已经没有Boost库好了,毕竟STL中仅仅提供了一些容器供编码者实用,Boost库相对而言全面了许多,所以更适合做一些项目的开发.但STL源码中依然有很多我们值得学习,思考的地方,包括现在大部分面试,都会问及到STL的框架源码部分.所以决定将这本书其中重要的几个部分拉出来做个笔记,以加深记忆并和大神们探讨探讨. 先简单介绍一下STL中的大致组成部分,一张图就明了

C++之STL简介

1. STL简介: 标准模板库(STL,即Standard Template Library),是一个C++软件库,也是C++标准程式库的一部分.模板是C++程序设计语言的一个比较新的重要特征,而标准模板库(STL)正是基于此特征.标准模板库(STL)使得C++编程语言在有了同Java一样强大的类库的同时,保有了更大的可扩展性. STL的代码从广义上讲分为三类:algorithm(算法).container(容器)和iterator(迭代器),几乎所有的代码都采用了模板类和模版函数的方式,这相比

STL之stack适配器的实现框架

说明:本文仅供学习交流,转载请标明出处,欢迎转载! 一提到适配器(adapter),我们就想到了早期用电话线上网所用的调制解调器,俗称"猫","猫"的作用是实现数模转化和模数转化,在客户端,它可以将电话的模拟信息转化为我们计算机能够接收的数字信息,所以猫相当于一个转换器.再举个更加好理解的例子来说明"适配器"的含义.相信在我们每个人的家里都有插排,假设就这么一种情况,现在我们家里的墙壁上只有一个三角的插口,而我们的电视却是两个口,怎么办?毫无疑问

STL之list容器的实现框架

说明:本文仅供学习交流,转载请标明出处,欢迎转载! list的底层采用数据结构是环形的双向链表, 相对于vector容器,list容器插入和删除操作付出的代价要比vector容器小得多,但是list带有链表的天生弱点,就是不支持随机访问.从内置的迭代器角度分析,vector容器对应的迭代器为随机访问迭代器,而list容器内置的迭代器则为双向迭代器. 我们也知道,STL中提供的很多算法都是基于随机访问迭代器的,如sort(b,e)函数,其所使用的迭代器就是随机访问迭代器,所以,list不能使用这类

STL之vector容器的实现框架

说明:本文仅供学习交流,转载请标明出处,欢迎转载. 实现vector容器的思路等同于实现一个动态数组,以下我们參照源代码的相关资料,给出一个vector容器的大致框架,仅仅有声明,没给出详细的实现. 代码的框架注意从下面几个方面给出: (1)空间分配属性,因为是对外封闭的,故为procted:        (2)共同拥有訪问的属性,可供外部用户訪问,定义为public:        (3)容器的构造函数与析构函数:        (4)vector容器的插入操作.        (5)vec

STL之容器适配器priority_queue的实现框架

说明:本文仅供学习交流,转载请标明出处,欢迎转载! 在前面的文章STL之heap相关操作算法中介绍了堆的相关操作算法,由于堆的注意主要作用是用于排序,我们也知道堆排序的时间复杂度为o(nlogn),是一种不稳定的排序算法,利用堆这一数据结构,我们可以很快第获取一个大数据中最大(或最小)的k个数.同时,上篇文章中,也提出了相关heap算法的一些问题. 问题1:在调用push_heap函数实现向堆中插入元素之前,我们必须要先将向底层容器的末端插入该元素,然后才能调用push_heap内部的向上调整来

STL之容器适配器queue的实现框架

说明:本文仅供学习交流,转载请标明出处,欢迎转载! 上篇文章STL之容器适配器stack的实现框架已经介绍了STL是如何借助基础容器实现一种常用的数据结构stack (栈),本文介绍下另外一种STL内部定义的另外一种STL容器适配器queue(队列). 对于接触过数据结构的人来说,队列并不陌生,它是一种FIFO(first in first out)的数据结构.与栈相比,队列的不同之处在于:(1)队列是一种先进先出的数据结构,而栈则是一种后进先出的数据结构:(2)队列支持首尾两端的访问操作,而栈

STL之deque容器的实现框架

说明:本文仅供学习交流,转载请标明出处,欢迎转载! vector底层采用的是一个数组来实现,list底层采用的是一个环形的双向链表实现,而deque则采用的是两者相结合,所谓结合,并不是两种数据结构的结合,而是某些性能上的结合.我们知道,vector支持随机访问,而list支持常量时间的删除,deque支持的是随机访问以及首尾元素的删除. deque是double ended queue的缩写,读作deck.首先我们用一个图来说明deque底层所采用的数据结构. 这个数据结构有一种似曾相识的感觉