STL初探——设计一个简单的空间配置器

  

#pragma once
#ifndef _M_ALLOCATOR
#define _M_ALLOCATOR
#include <new>            //用于定向开辟内存
#include <cstddef>        //用于存储中间量的类型,ptrdiff_t和size_t
#include <cstdlib>        //exit()
#include <climits>        //UINT_MAX
#include <iostream>       //cerr
namespace m_allocator
{
    template<class T>
    inline T* _m_allocate(ptrdiff_t size, T*)   //ptrdiff_t, 两个指针距离,个人你认为是long int类型
    {
        set_new_handler(0);                     //set_new_handler(0)主要是为了卸载目前的内存分配异常处理函数
                                                //这样一旦分配内存失败的话,C++就会强制性抛出std:bad_alloc异常,而不是跑到处理某个异常处理函数去处理
        T* temp = (T*)(::operator new((size_t)(size* sizeof(T*))));
        if (temp == 0)
        {
            cerr << "out of memory" << endl;
            exit(1);
        }
        return temp;
    }

//释放内存
template<class T>
inline void _m_deallocate(T* buffer)
{
    ::operator delete (buffer);
}

//开辟空间,构造对象
template<class T1, class T2>
inline void _m_construct(T1* p, const T2& value)
{
    new(p) T1(value);
}

//析构函数
template<class T>
inline void _m_destory(T* ptr)
{
    ptr->~T();
}

template<class T>
class _m_alloctor
{
public:
    typedef T                value_type;
    typedef T*                pointer;
    typedef const T*        const_pointer;
    typedef T&                referance;
    typedef const T&        const_referance;
    typedef size_t            size_type;
    typedef ptrdiff_t        difference_type;

    template<class U>
    struct m_rebind
    {
        typedef _m_alloctor<U> other;
    };

    pointer allocate(size_type n, const void* hint = 0)
    {
        return _m_allocate((difference_type)n, (pointer)0);
    }

    void deallocate(pointer p, size_type n)
    {
        _m_deallocate(p);
    }

    void construct(pointer p, const T& value)
    {
        _m_construct(p, value);
    }

    void destroy(pointer p)
    {
        _m_destory(p);
    }

    pointer address(referance x)
    {
        return pointer(&x);
    }

    const_pointer address(const_referance x)
    {
        return const_pointer(&x);
    }

    size_type max_size() const
    {
        return size_type(UINT_MAX / sizeof(T));
    }
};

}
#endif // !_M_ALLOCATOR
#include "m_allocator.h"
#include <vector>
#include <iostream>
using namespace std;

int main()
{
    int ia[5] = {0,1,2,3,4};
    unsigned int i = 0;
    vector<int, m_allocator::_m_alloctor<int> > iv(ia,ia + 5);

    for (auto i = iv.begin(); i != iv.end(); i++)
    {
        printf("%d", *i);
    }
    printf("%s", "\n");
    return 0;
}

  将以上空间配置器 m_allocator::_m_alloctor应用于程序中,只能有限度搭配PJ STL 和RW STL(两种不同版本STL源码),因为PJ STL未完全遵循STL规格,其所供应的许多容器都需要一个非标准的空间配置器接口allocator::_Charalloc(), 而RW STL在很多容器身上运用了缓冲区,情况更复杂,m_allocator

::_m_alloctor无法与之兼容,至于完全无法应用于SGI STL, 是因为SGI STL在这个项目上用上了自己所定义的一套标准,并没有太多遵循STL标准规格。

  事实上SGI STL仍然提供了一个标准的配置器接口simple_alloc,只是把它做了一层隐藏, 且缺省的空间配置器并不是该接口而已。

时间: 2024-10-13 12:53:03

STL初探——设计一个简单的空间配置器的相关文章

简单的空间配置器实现

这一节用到的小知识: 1.ptrdirr_t: ptrdiff_t是C/C++标准库中定义的一个与机器相关的数据类型.ptrdiff_t类型变量通常用来保存两个指针减法操作的结果.ptrdiff_t定义在stddef.h(cstddef)这个文件内.ptrdiff_t通常被定义为long int类型. 2.non-trivial constructor/destructor: 意思是"非默认构造函数/析构函数",这里的non-trivial指不是编译器自动生成的(函数)维基百科 我认为

STL源码剖析(1):空间配置器

STL所有的操作对象(所有的数值)都存放在容器之内,容器需要分配空间以存放数据.为什么不说allocator是内存配置器而是空间配置器,因为空间不仅是内存,空间也可以是磁盘或其它辅助储存媒体.这里我们主要讨论内存配置. SGI STL每个容器缺省的空间配置器为alloc,如vector: template<class T, class Alloc = alloc> class vector{--} 一般而言,C++的内存配置和释放操作如下: class Object{--}; Object*

STL源码分析--第二级空间配置器

本文讲解SGI STL空间配置器的第二级配置器. 相比第一级配置器,第二级配置器多了一些机制,避免小额区块造成内存的碎片.不仅仅是碎片的问题,配置时的额外负担也是一个大问题.因为区块越小,额外负担所占的比例就越大. 额外负担是指动态分配内存块的时候,位于其头部的额外信息,包括记录内存块大小的信息以及内存保护区(判断是否越界).要想了解详细信息,请参考MSVC或者其他malloc实现. SGI STL第二级配置器具体实现思想 如下: 如果要分配的区块大于128bytes,则移交给第一级配置器处理.

STL源码剖析 — 空间配置器(allocator)

前言 以STL的实现角度而言,第一个需要介绍的就是空间配置器,因为整个STL的操作对象都存放在容器之中. 你完全可以实现一个直接向硬件存取空间的allocator. 下面介绍的是SGI STL提供的配置器,配置的对象,是内存.(以下内容来自<STL源码剖析>) 空间配置器的标准接口 根据STL的规范,allocator的必要接口 各种typedef 1 allocator::value_type 2 allocator::pointer 3 allocator::const_pointer 4

2.1 空间配置器(allocator)

空间配置器隐藏在一切组件之后. 1.1 设计一个简单的空间配置器 根据STL的规范,以下是allocator的必要接口: allocator::value_type allocator::pointer allocator::const_pointer allocator::reference allocator::const_reference allocator::size_type allocator::difference_type allocator::rebind // 一个嵌套的(

STL学习笔记--2、空间配置器 allocator

2.1标准接口 allocator::value_type allocator::pointer allocator::const_pointer allocator::reference allocator::const_reference allocator::size_type allocator::difference_type allocator::rebind allocator::allocator()//默认构造函数 allocator::allocator(const allo

STL源码剖析 --- 空间配置器 std::alloc

STL是建立在泛化之上的.数组泛化为容器,参数化了所包含的对象的类型.函数泛化为算法,参数化了所用的迭代器的类型.指针泛化为迭代器,参数化了所指向的对象的类型.STL中的六大组件:容器.算法.迭代器.配置器.适配器.仿函数. 这六大组件中在容器中分为序列式容器和关联容器两类,正好作为STL源码剖析这本书的内容.迭代器是容器和算法之间的胶合剂,从实现的角度来看,迭代器是一种将operator*.operator->.operator++.operator-等指针相关操作予以重载的class tem

STL 之 空间配置器(allocator)

一.SGI 标准的空间配置器,std::allocator SGI也定义了一个符合部分标准,名为allocator的配置器,但是它自己不使用,也不建议我们使用,主要原因是效率不佳. 它只是把C++的操作符::operator new和::operator delete做了一层简单的封装而已. 二.SGI 特殊的空间配置器,std::alloc 由于SGI 标准的空间配置器只是把C++的操作符::operator new和::operator delete做了一层简单的封装,没有考虑到任何效率上的

使用lua实现一个简单的事件派发器

设计一个简单的事件派发器,个人觉得最重要的一点就是如何保证事件派发过程中,添加或删除同类事件,不影响事件迭代顺序和结果,只要解决这一点,其它都好办. 为了使用pairs遍历函数,重写了pairs(lua 5.2以上版本不需要): stdext.lua local _ipairs = ipairs function ipairs(t) local mt = getmetatable(t) if mt and mt.__ipairs then return mt.__ipairs(t) end re