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

首先需要了解内存分配的一个过程:程序调用=》allocator=》new=》malloc=》操作系统分配。

然后要理解三个有关于new的概念

  1. new operator:分配内存并初始化对象,不可被重载
  2. operator new:只分配内存,不初始化对象,可被重载,相当于C的malloc
  3. placement new:对分配好的内存进行初始化

在这里插入图片描述

Foo * p = new (ptr) Foo(value);  // ptr指向已经分配内存的起始位置

SGI配置器

SGI STL的配置器与标准规范不同,其名称为alloc而非allocator,不接受任何参数。所以在VC或CB需要这么指定配置器:

vector<int,std::allocator<int>> iv;

而在GCC中,需这样指定:

vector<int,std::alloc<int>> iv;

但其实SGI STL也支持allocator,只是效率不佳,仅仅对::operator new做了一层薄薄的封装。

一般来说,以下代码分为两阶段:(1)调用::operator new配置内存;(2)调用Foo::Foo()构造对象内容。

Foo* pf=new Foo;

STL alloc将这两阶段分开,内存配置交给alloc::allocate()负责,对象构造交给::construct()负责。

配置器定义于< memory>中,SGI <memory>内含两个文件

<stl_alloc.h>:负责内存空间的配置和释放

<stl_construct.h>:负责对象内容的构造和析构

还有个重要的文件 <stl_uninitialized.h>:用来fill或copy大块内存数据

stl_construct.h

定义了全局函数construct() 和 destroy()

construct() 核心代码

// 将初值 __value 设定到指针所指的空间上。
template <class _T1, class _T2>
inline void _Construct(_T1* __p, const _T2& __value) {
  new ((void*) __p) _T1(__value);   // placement new,调用 _T1::_T1(__value);
}

destroy()核心代码

// 第一个版本,接受一个指针,准备将该指针所指之物析构掉。
template <class _Tp>
inline void _Destroy(_Tp* __pointer) {
  __pointer->~_Tp();
}

// 第二个版本,接收两个迭代器。
// 调用 __VALUE_TYPE() 获得迭代器所指对象的类别
template <class _ForwardIterator>
inline void _Destroy(_ForwardIterator __first, _ForwardIterator __last) {
  __destroy(__first, __last, __VALUE_TYPE(__first));
}

其实destroy还有一个需要判断的地方:

 判断value_type时,如果这些元素有自己的析构函数,则这个析构函数叫做non-trivial destructor(构造函数、析构函数、拷贝构造函数、复制构造函数都可能是non-trivial)。

POD类型是C++的内建类型或传统C结构体类型,必有trivial ctor/dtor/copy/assignment四种函数。

若value_type没有non-trivail destructor,则说明这个对象的析构是无意义的,因而不需要一次又一次地调用那些无关痛痒的析构函数,直接调用malloc()、memcpy()等内存操作提高性能。

判断value_type是否有non-trival destrory的方法:

// 利用__type_traits<T>判断一个对象的所述类,进而得知该类型的析构函数是否需要做什么。
// 如果为true,则什么也不用做;否则,逐个调用第一个版本的析构函数
template <class _ForwardIterator, class _Tp>
inline void 
__destroy(_ForwardIterator __first, _ForwardIterator __last, _Tp*)
{
  typedef typename __type_traits<_Tp>::has_trivial_destructor
          _Trivial_destructor;
  __destroy_aux(__first, __last, _Trivial_destructor());
}

内存分配方面的内容(<stl_alloc.h>, <stl_uninitialized.h>),由于篇幅限制,放到下一篇讲了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值