美文网首页
关于STL内存管理的一点琐事(上)

关于STL内存管理的一点琐事(上)

作者: zhou的技术小庄园 | 来源:发表于2021-07-20 00:13 被阅读0次

    前言:

    (前置知识:你至少使用过STL里面得一种容器,你得熟悉模板,你得熟悉c++基本语法)

    以程序员使用STL的角度而言,STL空间分配器(allocator/alloc(组件之外))是程序员不需要考虑但是又不得不考虑的事情,他总是隐藏在幕后,默默工作的组件,但是对于容器而言,这个组件却起着至关作用的作用,默默工作,默默付出着。但是在介绍STL各种容器之前,分配器却是不得不要首先提及的。这里有些一点点矛盾的地方,你可以懂得如何使用容器,使他成为你的工具,为你解决各种需求而不必掌握其内部原理,但是这往往是你在某个技术上的一个瓶颈,当你不断的去理解,不断地去剖析,你就会越来越接近幕后的真相。下面,开始我们的topic。

    介绍:

    根据STL有关的规范(这个如何读者尚不知晓,如果有空,会整理出STL有关事宜,就现在而言,这个不是我们关注的主题),alloocator必须提供以下接口:

    allocator::value_type

    allocator::pointer

    allocator::reference

    allocator::const_reference

    allocator::const_pointer

    allocator::size_type

    allocator::difference_type

    allocator::rebind

    allcator::allocator()      default constructor

    allcator::allocator(const allocator &)  copy constructor

    template <class U> allocator::allocator(const allocator <U>&)  泛化的copy constructor(有关于泛化,特化,偏特化等特性,读者可以自行查百度搜素,这里不是我们关注的重点)

    allocator::~allocator()  default destructor

    pointer allocator::address(reference x)const  //返回某个对象的地址。例如:a.address(x)等同于 &x

    pointer allocator::allocate(size_type n, const void *=0) 配置空间,为n个T对象分配空间(这里的T,是指传入模板中的参数)

    void allocator::deallocate(pointer p, size_type n) //归还先前配置的空间

    void allocator::construct(pointer p,const T&x) 等同于new((void*)p) T(x),不懂这个语法的同学也没关系,这个叫placement new,new一块内存,用p指向它、并用x初始化,这个我相信也是很少人用到这个东西吧(嘻嘻)

    void allocator::destory(pointer p) //里面调用了p-> ~T();

    现在,我们大致对里面allocator里面的一些函数有了大致的了解,也许你读到这里你会一头雾水,但是没关系,现在我们来实现自己的空间分配器

    自己实现:

    #ifndef _ZZXMEM_

    #define _ZZXMEM_

    #include<new>

    #include<cstddef>//ptrdiff_t size_t

    #include<cstdlib>

    #include<climits>

    #include<iostream>

    using namespace std;

    namespace zx

    {

    template<class T>

    inline T* _allocate(ptrdiff_t size, T *)

    {

    set_new_handler(0);

    T* tmp = (t*)(::operator new((size_t)(size * sizeof(T))));

    if (NULL == tmp)

    {

    cerr << "out of memory!" << endl;

    exit(1);

    }

    return tmp;

    }

    template<class T>

    inline void _deallocate(T* buffer)

    {

    ::operator delete(buffer);

    }

    template<class T1,class T2>

    inline void _construct(T1* p, const T2& value)

    {

    new(p) T1(value);

    }

    template <class T>

    inline void _destory(T* p)

    {

    p->~T();

    }

    template<class T>

    class allocator {

    public:

    typedef T value_type;

    typedef T* pointer;

    typedef T& reference;

    typedef const T* const_pointer;

    typedef const T& const_reference;

    typedef size_t size_type;

    typedef ptrdiff_t difference_type;

    template<class U>

    struct rebine

    {

    typedef allocator<U>  other;

    };

    pointer allocate(size_type n, const void* hint = 0)

    {

    return _allocate((difference_type)n, (pointer)0);

    }

    void deallocate(pointer p, size_type n)

    {

    _deallcate(p);

    }

    void construct(pointer p, const T& value)

    {

    _construct(p, value);

    }

    void destory(pointer p)

    {

    _destory(p);

    }

    const_pointer const_address(const_reference x)

    {

    return (const_pointer)&x;

    }

    size_type max_size()const

    {

    return size_type(UINT_MAX / sizeof(T));

    }

    };

    }

    #endif // !_ZZXMEM_

    那么如何使用呢?例如array这个容器,你将其第二参数绑定为你的allocatoe<int>就可以了。

    但是对STL有过了解的同学这里会发现,标准库使用的并不是这个分配器呀,貌似是std::alloc哦!?

    确实,这种分配器是有很大缺陷的,这种做法是作为第一级分配器来用的,对于对内存有极大偏执的人而言,这无非是极大的灾难。

    先不要急,很快我们就会剖析真正在STL使用的分配器,那就是STL里第二级分配器,里面使用嵌入式指针加内存池的做法。那种做法更加美妙,更加让人拍案叫绝!

    我们下次见!

    相关文章

      网友评论

          本文标题:关于STL内存管理的一点琐事(上)

          本文链接:https://www.haomeiwen.com/subject/yqskmltx.html