1.自定义控件配置器
#ifndef _JJALLOC_
#define _JJALLOC_
#include <new> //for placement new (定位new)
#include <cstddef> //for ptrdif_t,size_t
#include <cstdlib> //for exit()
#include <climits> // for UNIT_MAX
#include <iostream> //for cerr
namespace JJ
{
//用于分配内存
template<typename T>
inline T* _allocate(ptrdiff_t size,T*)
{
std::set_new_handler(0);//没有处理无法分配内存的回调函数,即随时可抛出异常
//分配内存用的是 ::operator new
T* tmp = (T*)::operator new((size_t)(size * sizeof(T)));
if(tmp==0)
{
std::cerr<<"out of memory"<<std::endl;
exit(1);
}
return tmp;
}
//对 ::operator new 分配的内存构造对象
template<typename T1,typename T2>
inline void _construct(T1 * p,const T2 & val)
{
//构造对象 对operator new 分配的内存不能用构造函数构造对象
//只能用 new 的定位new(placement new)形式构造对象
new (p) T1(val);
}
//用于 销毁对象
template <typename T>
inline void _destory(T *p)
{
p->~T();
}
//用于 释放内存
template <typename T>
inline void _deallocate(T* p)
{
::operator delete(p);
}
template<typename T>
class allocator
{
public:
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
//rebind allocator of type U
template<typename U>
struct rebind
{
typedef allocator<U> other;
};
//分配内存
pointer allocate(size_type n,const void* hint=0)
{
std::cout<<"分配内存"<< std::endl;
return _allocate((difference_type)n,(pointer)0);
}
//构造对象,这里construct与destory要不要都行
//因为全局函数construct()与destory()定义在stl_construct.h中
void construct(pointer *p,const T&val)
{
std::cout<<"构造对象"<< std::endl;
_construct(p,val);
}
//销毁对象
void destroy(pointer *p)
{
std::cout<<"销毁对象"<< std::endl;
_destory(p);
}
//释放内存
void deallocate(pointer p,size_type n)
{
std::cout<<"释放内存"<< std::endl;
_deallocate(p);
}
pointer address(reference x)
{
return (pointer)&x;
}
const_pointer const_address(const_reference &x)
{
return (const_pointer)&x;
}
size_type max_size()const
{
return size_type(UINT_MAX/sizeof(T));
}
};
}
#endif
2 上述代码重要点
1>将内存配置与对象构造分开,将对象析构与内存释放分开。这也是标准空间配置器的思想。
2>内存分配用的函数::operator new,类似malloc,实现内存的分配但不构造对象。对应的,内存释放用::operator delete。
3>对象构造用定位new(placement new);对象销毁用析构函数即可。
3 测试
#include <iostream>
#include <vector>
#include <string>
#include "2jjalloc.h"
using namespace std;
int main()
{
vector<string,JJ::allocator<string>> vi={"Hello","World"};
for(int i=0;i<vi.size();++i)
cout<<vi[i]<<endl;
return 0;
}
测试结果:
注意:
标准配置器定义于memory中,而空间配置器与负责对象构造和析构的函数是分开的。配置器定义在stl_alloc.h中,stl_construct.h中定义全局函数construct和destory函数负责对象的构造与析构。
问题是:在上面例子中,我重载了函数construct与destory,但是没有执行?
还有一个发现:
当上例子中,将函数allocate与deallocate换个函数名时,运行会报错:
解释: