C++ 空间配置器allocator类

allocator类

C++中,内存分配和对象构造紧密纠缠(new),就像对象析构和回收一样(delete)。如果程序员想接管内存分配,即将内存分配和对象构造分开,对于前者,主要是分配和释放未构造的原始内存;对于后者,主要是在原始内存中构造和撤销对象。

分配和释放未构造的原始内存 两种方法:

  • allocator类,提供可感知类型的内存分配;
  • 标准库中的opeator new和operator delete,它们分配和释放需要大小的原始、未类型化的内存;

在原始内存中构造和撤销对象 不同方法:

  • allocator类定义了名为construct和destroy的成员;
  • placement new表达式,接受指向未构造内存的指针;
  • 直接调用对象的析构函数来撤销对象;
  • 算法uninitialized_fill 和 uninitialized_copy,在目的地构造对象;

C++的STL中定义了很多容器,容器的第二个模板参数通常为allocator类型,标准库中allocator类定义在头文件memory中,用于帮助将内存分配和对象的构造分离开来。它分配的内存是原始的、未构造的。

表达式 说明
allocator<T> a  定义了一个名为a的allocator对象,它可以为类型T的对象分配内存
a.allocator(n)  分配一段原始的、未构造的内存,这段内存能保存n个类型为T的对象
a.deallocate(p, n)
释放T*指针p地址开始的内存,这块内存保存了n个类型为T的对象,p必须是一个先前由allocate返回的指针,

且n必须是p创建时所要求的大小,且在调用该函数之前必须销毁在这片内存上创建的对象。

a.construct(p, t) 在T*指针p所指向内存中构造一个新元素。运行T类型的复制构造函数用t初始化该对象
a.destory(p)  运行T*指针p所指向对象的析构函数
   
uninitialized_copy(b,e,b2)
从迭代器b和e指出的输入范围中拷贝元素到从迭代器b2开始的未构造的原始内存中,该函数在目的地构造元素,而不是给它们复制。

假定由b2指出的目的地足以保存输入范围中元素的副本

uninitialized_fill(b,e,t)  将由迭代器b和e指出的范围中的对象初始化为t的副本,假定该范围是未构造的原始内存,使用复制构造函数构造对象
uninitalized_fiil_n(b,e,t,n) 将由迭代器b和e指出的范围中至多n个对象初始化为t的副本,假定范围至少为n个元素大小,使用复制构造函数构造对象

      
    STL都会使用allocator类来为容器分配空间,例如:

#include <memory>

template <class T> class Vector {
    public:
        Vector(): elements(0), first_free(0), end(0) {}
        void push_back(const T&);

    private:
        static std::allocator<T> alloc; // object to get raw memory
        void reallocate();  // get more space and copy existing elements
        T* elements;        // pointer to first elment in the array
        T* first_free;      // pointer to first free element in the array
        T* end;             // pointer to one past the end of the array
};

template <class T> std::allocator<T> Vector<T>::alloc;

template <class T>
void Vector<T>::push_back(const T& t) {
    if (first_free == end) {
        reallocate();
    }
    alloc.construct(first_free, t);
    first_free++;
}

template <class T>
void Vector<T>::reallocate() {
    // compute size of current array and allocate space for twice as many elements
    std::ptrdiff_t size = first_free - elements;
    std::ptrdiff_t newcapacity = 2 * (size > 1 ? size : 1);
    T* newelements = alloc.allocate(newcapacity);

    std::uninitialized_copy(elements, first_free, newelements);

    for (T* p = first_free; p != elements; alloc.destroy(--p));

    if (elements) {
        alloc.deallocate(elements, end - elements);
    }

    elements = newelements;
    first_free = elements + size;
    end = elements + newcapacity;
}

      

原文地址:https://www.cnblogs.com/chenny7/p/12255961.html

时间: 2024-10-13 13:10:14

C++ 空间配置器allocator类的相关文章

[C++] 空间配置器——allocator类

1.new和delete有一些灵活性上的局限:new把内存分配和对象构造组合在了一起:delete将对象析构和内存释放组合在了一起. 2.当分配一大块内存时,我们通常计划在这块内存上按需构造对象,在此情况下,我们希望将内存分配和对象构造分离:这意味着我们可以分配大块内存,但只在真正需要的时候才真正执行对象创建操作. 3.allocator类,定义在头文件memory中,它帮助我们将内存分配和对象构造分离开来,它提供一种类型感知的内存分配方法,它分配的内存是原始的.未构造的.在分配内存时,它会根据

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

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

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

C++ STL学习之 空间配置器(allocator)

标签(空格分隔): C++ STL 众所周知,一般情况下,一个程序包括数据结构和相应的算法,而数据结构作为存储数据的组织形式,与内存空间有着密切的联系. 在C++ STL中,空间配置器便是用来实现内存空间(一般是内存,也可以是硬盘等空间)分配的工具,他与容器联系紧密,每一种容器的空间分配都是通过空间分配器alloctor实现的.理解alloctor的实现原理,对内存结构以及数据存储形式会有更清晰直观的认识. 1.两种C++类对象实例化方式的异同 在c++中,创建类对象一般分为两种方式:一种是直接

STL源码剖析——空间配置器Allocator#2 一/二级空间配置器

上节学习了内存配置后的对象构造行为和内存释放前的对象析构行为,在这一节来学习内存的配置与释放. C++的内存配置基本操作是::operator new(),而释放基本操作是::operator delete().这两个全局函数相当于C的malloc() 和free() 函数.而SGI正是以malloc() 和free() 完成内存的配置与释放. 考虑到小型区块可能造成的内存破碎问题,SGI设计了两级的空间配置器.第一级直接使用malloc() 和free() ,而第二级则视情况采用不同的策略:当

STL源码剖析——空间配置器Allocator#3 自由链表与内存池

上节在学习第二级配置器时了解了第二级配置器通过内存池与自由链表来处理小区块内存的申请.但只是对其概念进行点到为止的认识,并未深入探究.这节就来学习一下自由链表的填充和内存池的内存分配机制. refill()函数——重新填充自由链表 前情提要,从上节第二级配置器的源码中可以看到,在空间配置函数allocate()中,当所需的某号自由链表为空时,才会调用refill()函数来填充链表.refill()函数默认申请20块区块的内存(5行),但所得内存不一定就是20块,要看当前内存池的剩余情况和堆容量的

简单的空间配置器实现

这一节用到的小知识: 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指不是编译器自动生成的(函数)维基百科 我认为

SGI的特殊空间配置器

SGI的空间配置器allocator只是简单的new和delete的一层包装,没有提供效率的强化. 而一般C++内存配置和释放操作如下: class  Foo  { ... } Foo  *pf = new Foo; delete pf; new算式:1)使用new配置内存,2)使用Foo构造对象 delelte算式: 1)使用~Foo()将对象析构 ,2)使用delete释放内存 STL allocator 将这两阶段操作区分开来.内存配置操作由 alloc::allocate() 负责,内存

《STL源码剖析》空间配置器

空间配置器(allocator) 空间配置器按我的理解就是C++ STL进行内存管理的组件(包括内存的申请和释放):当然,不只是内存,还可以向硬盘申请空间: 我主要看了内存的配置与释放(这里"配置"就应该是"申请"的意思).STL对此设计的哲学主要包括以下四个方面: 1.向系统堆空间申请内存空间 2.考虑了多线程的情况下的申请: 3.考虑内存不足的应变措施: 4.考虑过多"小型区块"的内存碎片的问题: C++ 申请的基本动作是::operator