内容简介:stl 源码阅读之allocator配置器
作者: tiankonguse | 更新日期:
前段时间一个服务大量使用了hashmap,于是简单看了下hashmap的实现方式,发现需要先看allocator,这里记录一下。
背景
在看vertor, map, set, string源码时, 总会看到有个 _Alloc
相关的模板参数。
然后这些容器都是使用这个 _Alloc
管理内存的。
这里简单的记录下 _Alloc
的设计与源码实现, 为之后的容器记录做准备。
template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
class vector: protected _Vector_base<_Tp, _Alloc>;
template <typename _Key, typename _Tp, typename _Compare = std::less<_Key>,
typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
class map;
template<typename _CharT, typename _Traits, typename _Alloc>
class basic_string;
template<typename _CharT, typename _Traits = char_traits<_CharT>,
typename _Alloc = allocator<_CharT> >
class basic_string;
typedef basic_string<char> string;
注1:我这里都是阅读c++ 4.8版本的stl源码。
注2: 这里不去关系怎么管理内存来提高效率, 这里关系的是申请释放内存时做了哪些事。
面向用户的allocator
根据源码,可以看到, allocator
自身只是定义了一些类型,如指针,引用,值的类型等。
这里唯一不协调的就是 rebind
了,正常情况下我们使用不上这个功能,所以本片文章不做介绍,后续项目涉及到这个了再深入记录一下。
// /usr/include/c++/4.8/bits/allocator.h
template<typename _Tp>
class allocator: public __allocator_base<_Tp> {
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<typename _Tp1> struct rebind { typedef allocator<_Tp1> other;};
allocator() throw () {}
allocator(const allocator& __a) throw () : __allocator_base<_Tp>(__a) {}
template<typename _Tp1> allocator(const allocator<_Tp1>&) throw () {}
~allocator() throw () {}
};
中间件 __allocator_base
__allocator_base
只是一个中间符号, 用于指定默认使用那个内存分配器。默认是 new_allocator
.
// /usr/include/c++/4.8/bits/c++allocator.h
#if __cplusplus >= 201103L
namespace std
{
template<typename _Tp>
using __allocator_base = __gnu_cxx::new_allocator<_Tp>;
}
#else
// Define new_allocator as the base class to std::allocator.
#define __allocator_base __gnu_cxx::new_allocator
#endif
一种具体实现new_allocator
new_allocator
是最简单的内存管理实现,其他相关的实现还有 malloc_allocator
, __pool_alloc
, __mt_alloc
, bitmap_allocato
等。
我们看到, new_allocator
里面也定义了那些指针,引用,值的类型, 而且也定义了 rebind
, 这里不讨论基类与子类重复申明这些的作用。
真正有用的是分配内存函数 allocate
和 deallocate
, 还有构造和析构函数 construct
和 destroy
.
这四个函数的功能与其名字一样, 一个是申请释放内存的, 一个是构造和析构的。
由于容器一般提前申请内存了, 所以容器就有必要自己调用构造函数和析够函数.
其中的 allocate
函数和 construct
函数延伸出一个知识点: new operator
, operator new
, placement new
.
// /usr/include/c++/4.8/ext/new_allocator.h
template<typename _Tp>
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<typename _Tp1> struct rebind { typedef new_allocator<_Tp1> other; };
new_allocator() {}
new_allocator(const new_allocator&) {}
template<typename _Tp1> new_allocator(const new_allocator<_Tp1>&) {}
~new_allocator() {}
pointer address(reference __x) const {
return std::__addressof(__x);
}
const_pointer address(const_reference __x) const {
return std::__addressof(__x);
}
pointer allocate(size_type __n, const void* = 0) {
return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));
}
void deallocate(pointer __p, size_type) {
::operator delete(__p);
}
void construct(pointer __p, const _Tp& __val) {
::new ((void *) __p) _Tp(__val);
}
void destroy(pointer __p) {
__p->~_Tp();
}
size_type max_size() const { return size_t(-1) / sizeof(_Tp); }
};
new operator, operator new 与 placement new
operator new
是一个函数,我们可以重载,作用是申请指定大小的内存。
new operator
是一个我们熟悉的 new
,不可以重载,作用是调用 operator new
申请内存,并初始化, 一般用户调用。
placement new
是一个全局函数,不可重载,作用是允许我们在一个已分配的内存中主动初始化内存中的对象。
placement new
声明和使用如下:
//声明
void *operator new( size_t, void * p ) throw();
//使用, 返回值依旧是传入的指针。
void construct(pointer __p, const _Tp& __val) {
::new ((void *) __p) _Tp(__val);
}
正是由于 placement new
的存在, 我们才可以自己管理内存分配内存,并进行初始化。
欠下的帐
- 内存管理相关算法
- rebind作用
- allocator与基类重复定义的原因
- stl实现
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 源码分析(五)—配置篇
- 源码安装配置 Nginx 记录
- Nginx 源码:配置文件解析
- Nacos 源码分析(二):获取配置流程
- mybatis原理,配置介绍及源码分析
- Nginx源码阅读笔记-配置解析流程
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Java程序设计
宋中山 严千钧 等编 / 清华大学出版社 / 2005-8 / 27.00元
本书全面、系统地介绍了Java语言的基本概念、基本语法和编程方法。主要内容包括:Java语言概述、数据类型与运算符、流程控制语句、类与对象、继承与多态、异常处理、工具类和算法、Applet小应用程序、图形用户界面、输入和输出、Java多线程以及Java高级编程。每章后面附有习题,读者可参考使用。 本书内容丰富,结构合理,语言简洁,深入浅出,通俗易懂。基础知识与程序实例相结合,示例典型......一起来看看 《Java程序设计》 这本书的介绍吧!