关于STL allocator

stl allocator源码学习 概述 介绍几个allocator的源码实现:简单的对operator new和operator delete进行封装的实现,vs2015中的实现,STLport中的实现,仿造STLport实现内存池。 1. 参考 http://www.cplusplus.com/reference/memory/allocator/ 《STL源码剖析》 《C++ Primer 第五版》 《Generi 阅读详情

关于STL 中allocator的接口与实现,C++标准有比较清楚的定义:allocator wiki


1. SGI STL版本的allocator并没有遵守C++标准。它只提供simple_alloc类共container使用,设计的allocator名字叫做alloc,有二级配置器。第一级配置采用malloc/free来实现allocate/deallocate,第二级配置器采用针对申请的内存有特别处理,如果大小大于128字节,则转调用第一级配置来分配和释放内存,否则采用memory pool的方式来分配这些小额的内存。在SGI STL中,默认采用第二级内存分配器。具体的可以阅读侯捷的《STL源码剖析》第二章。
在SGI STL 3.3中,已经提供了一个符合C++标准的allocator接口,通过对内部的alloc转调用来实现。

a)
b)
c)
d)
e)


2. GNU C++的STL内部借鉴SGI STL的实现,不过它对外的的STL allocator严格遵守C++的标准:


看一下它的代码:(定义在bits/allocator.h文件中)
namespace std
{
template
class allocator;


template<>
class allocator
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef void* pointer;
typedef const void* const_pointer;
typedef void value_type;


template
struct rebind
{ typedef allocator other; };
};


/**
* @brief The "standard" allocator, as per [20.4].
*
* (See @link Allocators allocators info @endlink for more.)
*/
template
class allocator: public ___glibcxx_base_allocator
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef _Tp* pointer;
typedef const _Tp* const_pointer;
typedef _Tp& reference;
typedef const _Tp& const_reference;


typedef _Tp value_type;


template
struct rebind
{ typedef allocator other; };


allocator() throw() { }


allocator(const allocator& a) throw()
: ___glibcxx_base_allocator(a) { }


template
allocator(const allocator&) throw() { }


~allocator() throw() { }


// Inherit everything else.
};


template
inline bool
operator==(const allocator&, const allocator&)
{ return true; }


template
inline bool
operator!=(const allocator&, const allocator&)
{ return false; }


// Inhibit implicit instantiations for required instantiations,
// which are defined via explicit instantiations elsewhere.
// NB: This syntax is a GNU extension.
#if _GLIBCXX_EXTERN_TEMPLATE
extern template class allocator;


extern template class allocator;
#endif


// Undefine.
#undef ___glibcxx_base_allocator
} // namespace std

template 类___glibcxx_base_allocator 定义在具体的平台相关的头文件中,例如i386-redhat-linux/bits/c++allocator.h:
// Define new_allocator as the base class to std::allocator.
#include <ext/new_allocator.h>
#define ___glibcxx_base_allocator __gnu_cxx::new_allocator</code>


根据GCC/libstdc++的 DOC, 知道
The current default choice for allocator is __gnu_cxx::new_allocator.
可以看出GNU c++的allocator其实采用的是new/delete-based allocation.
namespace __gnu_cxx
{
/**
* @brief An allocator that uses global new, as per [20.4].
*
* This is precisely the allocator defined in the C++ Standard.
* - all allocation calls operator new
* - all deallocation calls operator delete
*
* (See @link Allocators allocators info @endlink for more.)
*/
template
class new_allocator
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef _Tp* pointer;
typedef const _Tp* const_pointer;
typedef _Tp& reference;
typedef const _Tp& const_reference;
typedef _Tp value_type;


template
struct rebind
{ typedef new_allocator other; };


new_allocator() throw() { }


new_allocator(const new_allocator&) throw() { }


template
new_allocator(const new_allocator&) throw() { }


~new_allocator() throw() { }


pointer
address(reference __x) const { return &__x; }


const_pointer
address(const_reference __x) const { return &__x; }


// NB: __n is permitted to be 0. The C++ standard says nothing
// about what the return value is when __n == 0.
pointer
allocate(size_type __n, const void* = 0)
{ return static_cast(::operator new(__n * sizeof(_Tp))); }


// __p is not permitted to be a null pointer.
void
deallocate(pointer __p, size_type)
{ ::operator delete(__p); }


size_type
max_size() const throw()
{ return size_t(-1) / sizeof(_Tp); }


// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 402. wrong new expression in [some_] allocator::construct
void
construct(pointer __p, const _Tp& __val)
{ ::new(__p) _Tp(__val); }


void
destroy(pointer __p) { __p->~_Tp(); }
};


template
inline bool
operator==(const new_allocator&, const new_allocator&)
{ return true; }


template
inline bool
operator!=(const new_allocator&, const new_allocator&)
{ return false; }
} // namespace __gnu_cxx


不过GNU GCC提供了更多很有意思的定制allocator: __gnu_cxx::malloc_allocator(malloc_allocator.h)</em>, __gnu_cxx::bitmap_allocator (bitmap_allocator.h), __gnu_cxx::pool_allocator(pool_allocator.h), and __gnu_cxx::__mt_alloc(mt_allocator.h)


可通过--enable-libstdcxx-allocator 选项来开启其它的allocator,或者在定义一个container时,显式的描述模板参数表示用哪一个allocator:

#include <ext/malloc_allocator.h>
std::vector<int, __gnu_cxx::malloc_allocator<int> > malloc_vector;




3. MSVC的STL采用了P.J. Plauger的版本:allocator类定义在了include/xmemory文件中(以VS2008为例):
// TEMPLATE FUNCTION _Allocate
template<class _Ty> inline
_Ty _FARQ *_Allocate(_SIZT _Count, _Ty _FARQ *)
{ // check for integer overflow
if (_Count <= 0)
_Count = 0;
else if (((_SIZT)(-1) / _Count) < sizeof (_Ty))
_THROW_NCEE(std::bad_alloc, NULL);


// allocate storage for _Count elements of type _Ty
return ((_Ty _FARQ *)::operator new(_Count * sizeof (_Ty)));
}


// TEMPLATE FUNCTION _Construct
template<class _T1,
class _T2> inline
void _Construct(_T1 _FARQ *_Ptr, const _T2& _Val)
{ // construct object at _Ptr with value _Val
void _FARQ *_Vptr = _Ptr;
::new (_Vptr) _T1(_Val);
}


// TEMPLATE FUNCTION _Destroy
template inline
void _Destroy(_Ty _FARQ *_Ptr)
{ // destroy object at _Ptr
_DESTRUCTOR(_Ty, _Ptr);
}


template <> inline
void _Destroy(char _FARQ *)
{ // destroy a char (do nothing)
}


template <> inline
void _Destroy(wchar_t _FARQ *)
{ // destroy a wchar_t (do nothing)
}

它的_Allocate模板函数直接采用全局的operator new来分配内存。
// TEMPLATE CLASS _Allocator_base
template
struct _Allocator_base
{ // base class for generic allocators
typedef _Ty value_type;
};


// TEMPLATE CLASS _Allocator_base
template
struct _Allocator_base
{ // base class for generic allocators for const _Ty
typedef _Ty value_type;
};


// TEMPLATE CLASS allocator
template
class allocator
: public _Allocator_base
{ // generic allocator for objects of class _Ty
public:
typedef _Allocator_base _Mybase;
typedef typename _Mybase::value_type value_type;
typedef value_type _FARQ *pointer;
typedef value_type _FARQ& reference;
typedef const value_type _FARQ *const_pointer;
typedef const value_type _FARQ& const_reference;


typedef _SIZT size_type;
typedef _PDFT difference_type;


template
struct rebind
{ // convert an allocator to an allocator
typedef allocator other;
};


pointer address(reference _Val) const
{ // return address of mutable _Val
return (&_Val);
}


const_pointer address(const_reference _Val) const
{ // return address of nonmutable _Val
return (&_Val);
}


allocator() _THROW0()
{ // construct default allocator (do nothing)
}


allocator(const allocator&) _THROW0()
{ // construct by copying (do nothing)
}


template
allocator(const allocator&) _THROW0()
{ // construct from a related allocator (do nothing)
}


template
allocator& operator=(const allocator&)
{ // assign from a related allocator (do nothing)
return (*this);
}


void deallocate(pointer _Ptr, size_type)
{ // deallocate object at _Ptr, ignore size
::operator delete(_Ptr);
}


pointer allocate(size_type _Count)
{ // allocate array of _Count elements
return (_Allocate(_Count, (pointer)0));
}


pointer allocate(size_type _Count, const void _FARQ *)
{ // allocate array of _Count elements, ignore hint
return (allocate(_Count));
}


void construct(pointer _Ptr, const _Ty& _Val)
{ // construct object at _Ptr with value _Val
_Construct(_Ptr, _Val);
}


void destroy(pointer _Ptr)
{ // destroy object at _Ptr
_Destroy(_Ptr);
}


_SIZT max_size() const _THROW0()
{ // estimate maximum array size
_SIZT _Count = (_SIZT)(-1) / sizeof (_Ty);
return (0 < _Count ? _Count : 1);
}
};


// allocator TEMPLATE OPERATORS
template inline
bool operator==(const allocator&, const allocator&) _THROW0()
{ // test for allocator equality (always true)
return (true);
}


template inline
bool operator!=(const allocator&, const allocator&) _THROW0()
{ // test for allocator inequality (always false)
return (false);
}


// CLASS allocator
template<> class _CRTIMP2_PURE allocator
{ // generic allocator for type void
public:
typedef void _Ty;
typedef _Ty _FARQ *pointer;
typedef const _Ty _FARQ *const_pointer;
typedef _Ty value_type;


template
struct rebind
{ // convert an allocator to an allocator
typedef allocator other;
};


allocator() _THROW0()
{ // construct default allocator (do nothing)
}


allocator(const allocator&) _THROW0()
{ // construct by copying (do nothing)
}


template
allocator(const allocator&) _THROW0()
{ // construct from related allocator (do nothing)
}


template
allocator& operator=(const allocator&)
{ // assign from a related allocator (do nothing)
return (*this);
}
};



实现自定义的 STL allocator STL allocator 的注释讲解请见:http://blog.csdn.net/lifesider/archive/2011/06/06/6527776.aspx 这里实现的自定义allocator是继承自std::allocator,因为两者有公共部分,对于完全重写的allocator,下面的内容就不用读了。 上源码#include templateclas 阅读详情

相关推荐

STL 空间配置器 allocator

`STL` 空间配置器 `allocator``STL` 标准下的 `allocator`神奇的 `SGI STL``SGI` 里效率低下的 `std::allocator``SGI` 里正规的 `std::alloc`构造 `construct()` & 析构 `destroy()``alloc` 设计哲学`alloc` 的第一级配置器:`__malloc_alloc_template``alloc` 的第二级配置器:`__default_alloc_template` 无私奉献的 alloca

weixin_46323890的博客 652

[C标准库].P.J.Plauger.扫描版

在压缩包里面有C标准pdf书籍,教你如何使用C语言的标准库,还有如何写出来标准库

实现自己的STL配置器allocator

实现自己的STL配置器 STL所有数据都存储在容器之中,而容器需要配置空间以置放资料,所以配置器就是完成这一个任务的。 以下是它的一些接口 allocator::value_type //类型,如int allocator::pointer //指针,如int * allocator::const_pointer allocator::reference allocator::const_...

c++ 706

ANSI《C标准库》P.J.plauger的著作;也就是我们经常调用的库函数接口

----也就是/usr/lib目录下比较常见的libc.a, 如果我们想直到printf之类的c库函数的实现细节,可以查它

C++ STL学习笔记】C++ STL基础

文章目录C++ STL是什么,有什么用?学STL能干什么?C++ STL的发展历程是怎样的?C++ STL版本有哪些?HP STLSGI STLSTLportPJ STLRouge Wave STL熟练使用STL标准库是每个C++程序员的必备技能!泛型是什么,C++泛型编程又是什么?C++ STL基本组成(6大组件+13个头文件)如何衡量一个算法的执行效率?GNU开源精神及其发展历程 C++ STL是什么,有什么用? 在已有 C++ 尤其是 C++ 模板的基础上,从本节开始,我们开始系统地学习 STL 标准

qq_41854911的博客 3061

C++STL心法#1-STL版本介绍及源码下载编译

学习STL前要知道的哪些事;STL入门知识;STL学习环境搭建;cygnus安装;cygnus for windows

Allen Roson 3059

C++STL标准模版库

(standard template libaray-标准模板库):C++编程语言的一个,它提供了一组通用的模板类和函数,以实现常见的数据结构和算法。STL的设计目标是提供一种高效、灵活和通用的编程工具,使C++开发人员能够更轻松地实现各种功能而不必从头开始编写代码。

谁在夜里看海.的博客 1453

P.J.Plauger<ctype.h>

//http://www.lellansin.com/c标准库-ctype-h-_ctype转换表原理.html

you 1145

xmemory std::allocator源代码及注释

 //D:/Program Files/Microsoft Visual Studio 8/VC/include/xmemory // xmemory internal header (from )#pragma once#ifndef _XMEMORY_#define _XMEMORY_#ifndef RC_INVOKED#include #include #include #inclu

sunwenjun的专栏 4265

关于STL Allocator

看到一个线程池的实现代码里用到了STLAllocator,翻了一篇文章读读。

ThinkHY的专栏 1471

浅析STL allocator

转载自 一般而言,我们习惯的 C++ 内存配置操作和释放操作是这样的: 1 class FOO{}; 2 FOO *pf = new FOO; 3 delete pf; 我们看其中第二行和第三行,虽然都是只有一句,当是都完成了两个动作。但你 new 一个对象的时候两个动作是:先调用::operator new 分配一个对象大小的内存,然后在这个内存上调用FOO::FOO()构造对象。同样...

teslali 2996

深入理解 STL allocator

由于std::set,std::multiset,std::map,std::multimap四种容器的插入删除操作性能高并且自动排序,在很多时候比如需要动态操作时往往会使用它们,然后由于容器内部使用的是节点,每次的插入或删除都要调用new或delete,往往容易造成碎片和性能下降,于是自定义的allocator出现了。这篇文章的目的就是详细讲解std::allocator的内部结构,为实现自

lifesider 1万+

STL中的空间配置器allocator的实现原理及源码剖析

allocatorSTL为自己的模版容器所设计的标准空间配置器。处于std命名空间下 今天我要讲的的allocator的源码在我的github上,地址为 mySTL 是我模仿标准STL写出的代码,并添加了注释。allocator简介allocator为一个模版类,我们使用的时候一般都会将其绑定到一个具体的类型上。如下:allocator<int> alc;allocator大致需要实现如下功能:

我的大学 4086

C++ STL——allocator

C++ 标准模板库提供了一个非常重要的内存管理机制——allocator。它对内存管理接口进行了封装,实现了对象内存分配与构造分离、对象析构与内存释放分离。标准库中通过模板参数为容器提供内存管理策略,allocator 就是一种具体的策略,我们可以实现基于共享内存、内存池的 自定义 allocator 把它们应用于容器。本文章将以 MSVC 的 allocator 框架为参考,讲述 allocator 的核心工作原理。

ypy9323的博客 591

stl allocator

stl allocator实现

sjc960115的博客 545

STL中的Allocator

最近在看STL,写一点博客。 关于一些细节可能就不放上来了,就写一些我自己的心得。 1.为什么要用Allocator C++容器的设计思路是,对存放到里面的东西是拷贝一份放进去。 而且里面的空间都是动态分配的。 所以在构建容器的时候,需要必要的①内存分配②构造对象。 2.new operator、operator new、placement new

山鸡哥的专栏 1365

STL 配置器(allocator)

配置器:负责空间配置与管理,从实现的角度来看,配置器是一个实现了动态空间配置、空间管理、空间释放的 class template。 空间配置器:整个 STL 的操作对象(所有的数值)都存放在容器之内,而容器一定需要配置空间以存放内容。 什么是 allocatorallocator 有什么用? 我们需要对 C++allocator 的堆内存接口调用顺序有个清晰的认识,如下图所示。 allocator 堆内存管理接口 STL 的容器(eg: vector、stack、deque等)有一个共同特征,就是

南宫封清的博客 1352
上一篇: 专访C++之父Bjarne Stroustrup
下一篇: 函数模板知识点梳理
zero_lee
博客等级 码龄21年 94粉丝 91原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值