STL学习笔记(1)空间配置器 allocator

1 简述

    STL其他组件都是存放在空间配置器配置的空间中,此处空间可以是内存,也可以是磁盘或其他辅助存储介质。
    allocator负责内存的分配和释放,以及负责对象的构造和析构,两个操作时分开的。
    每个容器都已经制定了默认的空间配置器Alloc,如下图所示。
在这里插入图片描述
若要使用自己的空间配置器则必须vector<int,my_alloc> mv;

2 标准接口

// 以下几种自定义类型是一种type_traits技巧,暂时不需要了解
allocator::value_type
allocator::pointer
allocator::const_pointer
allocator::reference
allocator::const_reference
allocator::size_type
allocator::difference

allocator::rebind
// 一个嵌套的(nested)class template,class rebind<U>拥有唯一成员other,那是一个typedef,代表allocator<U>

allocator::allocator() // 默认构造函数
allocator::allocator(const allocator&) // 拷贝构造函数
template <class U>allocator::allocator(const allocator<U>&) // 泛化的拷贝构造函数
allocator::~allocator() // 析构函数


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

const_pointer allocator::address(const_reference x) const
// 返回某个const对象的地址,a.address(x)等同于&x


pointer allocator::allocate(size_type n, const void* = 0)
// 配置空间,足以存储n个T对象。第二个参数是个提示。实现上可能会利用它来增进区域性(locality),或完全忽略之

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


size_type allocator:maxsize() const// 返回可成功配置的最大量


void allocator::construct(pointer p, const T& x)
//在p指向位置 调用对象的构造函数,等同于 new((void*)p) T(x)

void allocator::destroy(pointer p)// 调用对象的析构函数,等同于 p->~T()

3 空间配置器申请的空间均仅仅是空间(如仅分配内存而未构造对象)

这里说明几种申请内存的区别

  • A *a = (A*)(::operator new A ((size_t) (size * sizeof(A)));
      调用全局operator new(size_t size)仅仅申请内存,然后返回指针。allocate中使用。
  • void *mem = operator new A (sizeof(T1),p);
      借用p指向的内存处大小为sizeof(T1)的内存,返回void*指针。
  • A *a = new A (...);
      ①申请内存(与operator new相同)
      ②调用A(…)构造对象
      ③返回指针
//Complex* pc=new Complex(1,2)相当于
		try{
   
			void* mem = operator new(size(Complex));
			Complex* pc=static_case<Complex*>(mem);
			pc->Complex()::Complex(1,2);
		}
		catch(std::bad_alloc){
    ... }
  • new(p) T1(value);
      为已申请内存*p构造T1。construct时使用。相当于
		try{
   
			void* mem = operator new(size(T1),p);
			p* pc=static_case<T1*>(mem);
			pc->T1()::T1();
		}
		catch{
    ... }

4 SGI空间配置器

SGI的空间配置器名称为alloc,而非allocator,不接受任何参数。

vector<int,allocator<int>> iv;
vector<int,alloc> iv;

我们所习惯的c++内存配置操作和释放操作是使用newdelete来完成的:

class Foo {
    ... };
Foo* pf = new Foo; // 配置内存,然后构造对象
delete pf; // 将对象析构,然后释放内存

如上一部分所说,其中的new 操作符(new operator)包含两阶段操作:
  (1)调用operator new配置内存
  (2)调用Foo::Foo( )构造函数构造对象内容。
delete操作符同样也包含两阶段操作:
  (1)调用Foo::~Foo( )析构函数将对象析构。
  (2)调用operator delete释放内存
STL allocator 将这两阶段操作区分开来。
内存配置操作由 alloc::allocate() 负责,内存释放操作由 alloc::deallocate() 负责;
对象构造操作由 ::construct() 负责,对象析构操作由 ::destroy() 负责。

//负责内存空间的配置与释放;
<stl_alloc.h>//文件中定义了一、二两级配置器,彼此合作,配置器名为alloc。

//负责对象内容的配置与释放
<stl_construct.h>//全局函数construct()和destroy(),负责对象的构造和析构。

//用来填充fill或复制copy大块内存数据
<stl_uninitialized.h>//uninitialized_copy();uninitialized_fill();uninitialized_fill_n
uninitialized_copy(first, last, result) //将[first,last)范围内的对象复制到result处;
uninitiated_fill(first, last, X) //将[first,last)范围内的内存用对象X的副本填充;
uninitiated_fill_n(first, n, X) //将first开始的n个连续的内存空间用X的副本填充;


4.1 构造与析构工具:construct()和destroy()

  • construct()仅仅负责构造对象,需要提前用allocate()申请内存。两操作合起来相当于new。
      construct()接受一个指针p和初值value,该函数将初值设定到所指空间上;
  • destroy()仅仅负责析构对象,需要之后用deallocate()释放内存。两操作合起来相当于delete。
      destroy()有两个版本:
      
      1、接收一个指针,准备将该指针所指之物析构掉。直接调用该对象的析构函数;
      2、接收first和last两个迭代器,准备将[first,last)范围内的所有对象析构掉。
    利用value_type()获取迭代器所指对象的类型,利用__type_traits判断该类型的析构函数是否无关痛痒。若是__true_type,则什么也不做,反之若是__false_type则循环访问,对每个对象调用析构函数。
#ifndef __SGI_STL_INTERNAL_CONSTRUCT_H
#define __SGI_STL_INTERNAL_CONSTRUCT_H
#include <new.h>		// 欲使用 placement new,需先含入此檔

template <class T1, class T2>
inline void construct(T1* p, const T2& value) {
   
  new (p) T1(value); 	// placement new; 调用 T1::T1(value);
}

// 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值