GUN C++ STL中的vector的内存分配器
来源:互联网 发布:软件系统简介 编辑:程序博客网 时间:2024/05/18 00:27
- GUN C STL中的vector的内存分配器
- allocator_traits
GUN C++ STL中的vector的内存分配器
//vector 原型 默认情况下其内存配置器为std::allocator<_Tp>template <typename _Tp, typename _Alloc = std::allocator<_Tp>>class vector : protected _Vector_base<_Tp, _Alloc>;//_Vector_base原型template <typename _Tp, typename _Alloc>struct _Vector_base{typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template rebind<_Tp>::other _Tp_alloc_type;//stl源码剖析上说, 这个其实就是一个allocator<U>, 见alloc_traits//_Vector_base的一个内部类, 继承了这个allocatorstruct _Vector_impl : _Tp_alloc_type{ pointer _M_start;//目前使用的空间的开始指针 pointer _M_finish;//目前使用的空间的结尾指针 pointer _M_end_of_storage;//目前可用的空间的尾指针};};
看一个vector的构造函数
//调用形式:vector<string> v(10, "asd");vector( size_type __n, //构造函数结束时,会析构这个临时对象allocator const value_type &__value, const allocator_type &__a = allocator_type())//此处构造一个临时的allocator对象 : _Base(__n, __a){//基类复制了这个临时对象, 生成了自己的内部类 _M_fill_initialize(__n, __value);//这个是负责构造对象的}//调用基类的这个构造函数//发现父类中并没有负责对象的构造,只是负责内存的分配_Vector_base(size_t __n, const allocator_type &__a) : _M_impl(__a){//调用_M_impl复制构造 _M_create_storage(__n);//内存貌似在这儿分配的}//调用这个内部类的构造函数_Vector_impl(_Tp_alloc_type const& __a) _GLIBCXX_NOEXCEPT : _Tp_alloc_type(__a), _M_start(0), _M_finish(0), _M_end_of_storage(0){}//又调用其父类的_Tp_alloc_type复制构造函数,就是std::allocator<_Tp>//这是一个基类的protected函数void _M_create_storage(size_t __n){ this->_M_impl._M_start = this->_M_allocate(__n);//分配内存 this->_M_impl._M_finish = this->_M_impl._M_start;//里面还没有东西 this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __n;}//这是一个基类的public函数pointer _M_allocate(size_t __n){//分配的内存大小与调用vector时设置的大小一致 //默认情况下_Tp_alloc_type是std::allocator<_Tp>, 见alloc_traits typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Tr; return __n != 0 ? _Tr::allocate(_M_impl, __n) : 0;//调用该构造器的allocate函数分配内存}
再看_M_fill_initialize
void _M_fill_initialize( size_type __n, const value_type &__value){ std::__uninitialized_fill_n_a(this->_M_impl._M_start, __n, __value, _M_get_Tp_allocator()); this->_M_impl._M_finish = this->_M_impl._M_end_of_storage;}//头文件 stl_uninitialized.h中//此函数还有一个标准模版的版本, 最后一个参数是为了使用默认内存分配器std::allocator时使用这个版本template<typename _ForwardIterator, typename _Size, typename _Tp, typename _Allocator>void __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n, const _Tp& __x, _Allocator& __alloc);//使用自己的分配器时调用此函数template <typename _ForwardIterator, typename _Size, typename _Tp, typename _Tp2>inline void __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n, const _Tp& __x, allocator<_Tp2>&){//最后一个参数只是为了函数匹配 std::unitialialized_fill_n(__first, __n, __x);}//unitialialized_fill_n template<typename _ForwardIterator, typename _Size, typename _Tp> inline void uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x){ //value_type 是迭代器所指向的类型, vector的迭代器其实是一个Random Access Iterator typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;#if __cplusplus < 201103L const bool __assignable = true;#else // trivial types can have deleted assignment //利用traits技法"萃取"迭代器所指对象的类型是否支持'复制构造'和'operator='操作 //不过貌似这个一直都是true,即使这两个函数被声明为delete const bool __assignable = is_copy_assignable<_ValueType>::value;#endif //__is_trivial 提取迭代器所指对象是否有默认的构造函数 std::__uninitialized_fill_n<__is_trivial(_ValueType) && __assignable>:: __uninit_fill_n(__first, __n, __x);}//如果有默认构造//其中调用全局construct函数, 构造对象//如果没有默认够造函数//std::__uninitialized_fill_n<true>::__uninit_fill_n函数, 最终调用fill_n
vector是如何管理分配的内存大小的?
//左值引用版本//调用push_back(_Tp &)时, 会检查内存分配情况, 够不够新插入的元素//_Alloc_traits typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Alloc_traits;void push_back(const value_type &__x){ if(this->_M_impl._M_finish != this->_M_impl._M_end_of_storage){//检查是否有空间 _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, __x); ++this->_M_impl._M_finish;//有就直接构造对象了 }else//没有就分配空间再构造#if __cplusplus >= 201103L _M_emplace_back_aux(__x);#else _M_insert_aux(end(), __x);#endif}//右值引用版本
//_M_emplace_back_aux //声明在stl_vector.h中, 定义在vector.tcc文件中#if __cplusplus >= 201103Ltemplate<typename _Tp, typename _Alloc>template<typename... _Args>void vector<_Tp, _Alloc>::_M_emplace_back_aux(_Args&&... __args){ //从_M_check_len函数可以看出vector的内存分配策略 //原大小加上max(size(), 1) __n就是size_type(1) //const size_type __len = size() + std::max(size(), __n); const size_type __len = _M_check_len(size_type(1), "vector::_M_emplace_back_aux"); pointer __new_start(this->_M_allocate(__len));//开始分配内存 pointer __new_finish(__new_start);//调节尾指针/*---------------------------------------------------------------------------------*/ __try{//为了在构造了部分对象时,发生了异常,可以析构掉之前已经构造的对象 _Alloc_traits::construct(this->_M_impl, //先构造这个push_back的元素 __new_start + size(), //在start+size()位置构造 std::forward<_Args>(__args)...);//forward保持其左/右值引用属性 __new_finish = 0; __new_finish//移动元素,如果可以移动的话 C++primer 第五版 p474 = std::__uninitialized_move_if_noexcept_a (this->_M_impl._M_start, this->_M_impl._M_finish, __new_start, _M_get_Tp_allocator()); ++__new_finish; }__catch(...){//如果出现异常 if (!__new_finish)//如果在设置__new_finish = 0之前构造对象就出现异常,析构这一个对象 _Alloc_traits::destroy(this->_M_impl, __new_start + size()); else std::_Destroy(__new_start, __new_finish, _M_get_Tp_allocator()); _M_deallocate(__new_start, __len);//释放这块新内存 __throw_exception_again; }/*----------------------------------------------------------------------------------*/ std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, _M_get_Tp_allocator());//析构对象 _M_deallocate(this->_M_impl._M_start, this->_M_impl._M_end_of_storage - this->_M_impl._M_start);//释放内存 this->_M_impl._M_start = __new_start; this->_M_impl._M_finish = __new_finish; this->_M_impl._M_end_of_storage = __new_start + __len;//调节指针}#endif
allocator_traits
这个类中有内存配置器的大部分接口函数, 只是参数加一个allocator_type, 然后调用
//模版定义template <typename _Alloc>struct allocator_traits : __allocator_traits_base;//std::allocator即stl默认的内存配置器的特例化版本template <typename _Tp>struct allocator_traits<allocator<_Tp>>;
阅读全文
0 0
- GUN C++ STL中的vector的内存分配器
- STL中的内存分配器
- STL的内存分配器
- STL的内存分配器
- STL的内存分配器
- STL的内存分配器
- STL的内存分配器
- STL的内存分配器
- STL的内存分配器
- STL中的内存分配器原理
- STL中的内存分配器原理
- STL中的内存分配器原理
- SGI STL的内存分配器
- 内存管理之一:STL中的内存分配器
- 内存管理之一:STL中的内存分配器
- 内存管理之:STL中的内存分配器
- 内存管理之一:STL中的内存分配器
- 内存管理之一:STL中的内存分配器
- hdu 1230 perals
- 雷军——一个走上“歪路”的天才程序员
- inputstream
- Zookeeper的作用简介
- inputstreambuffer
- GUN C++ STL中的vector的内存分配器
- Access denied for user 'root'@'127.0.0.1'
- testfile
- [整理]GPS数据包解析
- 测试相关概念
- IntelliJ 中Maven pom.xml依赖不生效解决
- 大数据一虚拟机的安装(nat)
- InputStreamReader
- Java:继承的初始化顺序