一、STL内存分配器
分配器(allocator))是C ++标准库的一个组件, 主要用来处理所有给定容器(vector,list,map等)内存的分配和释放。C ++标准库提供了默认使用的通用分配器std::allocator,但开发者可以自定义分配器。 GNU STL除了提供默认分配器,还提供了__pool_alloc、__mt_alloc、array_allocator、malloc_allocator 内存分配器。 __pool_alloc :SGI内存池分配器 __mt_alloc : 多线程内存池分配器 array_allocator : 全局内存分配,只分配不释放,交给系统来释放 malloc_allocator :堆std::malloc和std::free进行的封装
二、STL allocator
1、STL allocator简介 new会分配内存并执行对象构造函数,delete会执行对象析构函数并释放内存。如果将内存分配和对象构造分离,可以先分配大块内存,只在需要时才真正执行对象构造函数。 STL在头文件memory中提供了一个allocator类,允许将分配和对象构造分离,提供更好的性能和更灵活的内存管理能力。为了定义一个allocator对象,必须指明allocator可以分配的对象类型。当allocator分配内存时,会根据给定的对象类型来确定恰当的内存大小和对齐位置。
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() { }
};
根据C++标准规范,STL中分配器的对外接口、成员变量都一样,只是接口内部实现有区别。 allocator实现在模板类new_allocator中:
template<typename _Tp>
class new_allocator
{
public:
typedef _Tp* pointer;
typedef const _Tp* const_pointer;
pointer
allocate(size_type __n, const void* = 0)
{
if (__n > this->max_size())
std::__throw_bad_alloc();
return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));
}
void
deallocate(pointer __p, size_type)
{ ::operator delete(__p); }
};
STL中容器默认分配器为std::allocator<_Tp>,内存分配和释放的接口allocate和deallocate内部实现只是将::operator new和::operator delete进行封装,没用做特殊处理。
3、STL allocator实例
#include <iostream>
#include <string>
#include <vector>
#include <memory>
using namespace std;
class base
{
public:
base(){ cout << "base ctor" << endl; }
~base(){ cout << "base dtor" << endl; }
base(const base &t){cout << "Copy ctor" << endl; }
};
int main(int argc, const char *argv[])
{
new_allocator<base> alloc_test;
base *ptest = alloc_test.allocate(3);
{
alloc_test.construct(ptest , base());
alloc_test.construct(ptest + 1, base());
alloc_test.construct(ptest + 2, base());
}
alloc_test.destroy(ptest);
alloc_test.destroy(ptest + 1);
alloc_test.destroy(ptest + 2);
alloc_test.deallocate(ptest , 3);
getchar();
return 0;
}
-----------------------------------
4、自定义allocator 实现Allocator只需要实现allocate和deallocate,来实现自己的内存分配策略。
template<class T >
inline T*_allocate(ptrdiff_t num,T*){
std::cout<<"_allocate"<<endl;
return static_cast<T*>(::operator new(num*sizeof(T)));
}
template <class T>
inline void _deallocate(T* buff){
std::cout<<"_deallocate"<<endl;
::operator delete(buff);
}
template <class T ,class U>
inline void _construct(T* p,const U& value){
new(p)T(value);
}
template<class T>
inline void _destory(T* p){
p->~T();
}
template<typename T>
class MyAlloctor{
public:
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef const T* const_pointer;
typedef const T& const_reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
template<typename _Tp1>struct rebind{ typedef allocator<_Tp1> other; };
MyAlloctor()=default;
~MyAlloctor()=default;
pointer address(reference x){
return static_cast<pointer>(&x);
}
const_pointer address(const_reference x){
return static_cast<const_pointer>(&x);
}
pointer allocate(size_type _n,const void* hit=0 ){
return _allocate(_n,(pointer)0);
}
void deallocate(pointer p,size_type _n){
_dealloctor(p);
}
size_type max_size()const throw(){
return static_cast<size_type>(INT_MAX/sizeof(T));
}
void construct(pointer p,const_reference value){
_construct(p,value);
}
void destroy(pointer p){
_destory(p);
}
};
测试代码:
#include <string>
#include <vector>
#include <iostream>
using namespace std;
class Base
{
public:
Base()
{
cout << "Base ctor" << endl;
}
Base(const Base& other)
{
cout << "Base Copy ctor" << endl;
}
~Base()
{
cout << "Base dtor" << endl;
}
};
class Drive:Base
{
public:
Drive()
{
cout << "Drivector" << endl;
}
Drive(const Drive& other)
{
cout << "Drive Copy ctor" << endl;
}
~Drive()
{
cout << "Drive dtor" << endl;
}
};
int main(void)
{
vector<string, Myallocator<string> > vec(10, "test");
vec.push_back("test1");
vec.push_back("test2");
Myallocator<Base>::rebind<Drive>::other alloc_test;
Drive*p1 = alloc_test.allocate(5);
alloc_test.construct(p1, Test2());
alloc_test.construct(p1 + 1, Test2());
alloc_test.construct(p1 + 2, Test2());
alloc_test.destroy(p1);
alloc_test.destroy(p1 + 1);
alloc_test.destroy(p1 + 2);
alloc_test.deallocate(p1, 3);
return 0;
}
|