• stl空间配置器简介


      1、 符合STL标准的空间配器接口

    STL是c++中使用非常广泛的一个标准库,它包含各种有用的容器。而空间配置器作为STL各种容器的背后的核心,负责容器内部内存的分配和释放。不过空间配置器可以分配的也不只是内存,因为空间也意味着可以是磁盘或者其他存储介质。下边是一个符合STL规范的空间配置器的必要接口:

    allocator::value_type

    allocator::pointer

    allocator::const_pointer

    allocator::reference

    allocator::const_reference

    allocator::size_type

    allocator::difference_type

    //上边这几个都是一些typedef定义,其中 size_type 和difference_type是stddef.h中 size_t, ptrdiff_t这两个类型的类型别名(ptrdiff_t是两个指针相减的结果)

    allocator::rebind

    allocator::allocator

    allocator::allocator(const allocator&)

    template<class U>

    allocator::allocator(const allocator(U)&)

    //泛化的拷贝构造函数

    allocator::~allocator()

    pointer allocator::address(reference X) const

    const_pointer allocator::address(const_reference X)const

    pointer allocator::allocator(size_type n, const void* = 0)

    void allocator::deallocate(pointer p, size_type n)

    //归还先前配置的空间

    size_type allocator::max_size() const

    void allocator::construct(pointer p, const T& x)

    void allocator::destrory(pointer p)

    2、 SGI空间配置器

    SGI STL的配置器与标准规范不同,其名称是alloc而不是allocator,而且不接受任何参数。如果在程序中需要明确使用SGI的配置器,我们不能采用标准写法:

    vector<int, std::allocator<int> > v

    需要这么写:

    vector<int, std::alloc> v

    通常情况下,我们使用的stl中的容器都是用标准配置器,而SGI STL的每一个容器都已经指定其缺省空间配置器为alloc,如:

    template <class T, class Alloc=alloc>

    class vector {…}

    2.1 标准空间配置器

    SGI STL也有一个符合标准,名为allocator的配置器,但SGI从未使用过它,因为它效率太低,只是对::operator new, ::operator delete的简单封装而已;下边我着重介绍SGI特殊的配置器alloc。

    2.2 SGI特殊空间配置器, std::alloc

    C++中,我们在申请内存和释放内存的时候,一般这样做:

    class Foo{}

    Foo* f = new Foo

    delete f

    这其中new操作符内部含有两阶段操作,(1)调用new申请内存, (2)调用Foo:Foo()即对象的构造函数构造对象内容。

    delete也含有两段操作:(1)调用Foo::~Foo()将对象析构, (2) 调用delete 释放内存。

    为了精密分工也更有效的利用内存,SGI alloc将这两个阶段分开来操作。内存配置有alloc::allocator()负责内存配置,alloc::deallocator()负责内存释放;::constructor()负责构造对象;::destrory负责析构对象。

    2.3内存配置后对象的构造与内存释放前对象的析构工具: constructor()和destrory()

    这两个函数为全局函数,符合stl规范。

    constructor()接受一个指针p和一个初值,该函数的作用是将初值设定到指针所指的内存空间上

    template<class T1, class T1>

    inlie void destructor(T1 *p, const T2 &value) {

    new (p) T1(value) //placement new 在一个已经分配的内存中创建对象

    }

    destroy()函数有两个版本,一个版本接受一个指针参数,直接调用这个指针所指对象的析构函数析构对象。

    template<class T>

    inline void destroy(T* pointer){

    pointer->~T();

    }

    另外一个版本接受两个迭代器,

    template<class ForwardIterator, class T>

    inline void destroy(ForwardIterator first, ForwardIterator last, T*) {

    }

    destroy函数实现的有点复杂,他先获取到迭代器所指对象的的类型,然后在看对象是否有trivial destructor, 如果有,调用一个什么也不做的版本;如果有non-trivial destructor,则遍历迭代器中的每一个对象,然后依次调用其析构函数。

    (这里主要是处于效率考虑, 如果一个对象的析构函数没有任何作用,那么循环调用这个函数对效率是一种伤害)。

    备注:

            什么是trivial destructor呢?举个例子来说,存在A,B两个类,其中类B含有一个数据成员C,C有析构函数需要释放一些内存;那么在这种情况下,A就含有trivial destructor, 而B则含有non-trivial destructor。

  • 相关阅读:
    keypress事件
    input输入框(blur,change,focus)
    click点击以后添加新class,删除其余同名class
    强制数组并且匹配Array
    模拟鼠标事件
    简单的form操作
    鼠标滚轮事件(mousewheel、DOMMouseScroll)
    事件委托技术
    从程序员到项目经理:项目经理必须懂一点“章法”
    JavaScript项目优化总结
  • 原文地址:https://www.cnblogs.com/yuxingfirst/p/3225929.html
Copyright © 2020-2023  润新知