网上 其他很多博主,写了很多STL的解析,大致和书上讲的都差不多,最近学到了空间配置器这部分,我就谈谈在学习STL 中的小小心得吧,要是有不对的地方,请大家指出。
首先看看下面这段代码,这中写法贯彻整个STL
typedef size_t size_type;
typedef _Ty* pointer;
typedef const _Ty* const_pointer;
typedef _Ty& reference;
typedef const _Ty& const_reference;
typedef _Ty value_type;
typedef ptrdiff_t difference_type;
这个应该叫做类型萃取,我个人目前理解的是便于阅读和泛型的使用,给大家贴个博客吧:http://blog.youkuaiyun.com/bit_clearoff/article/details/53728516这个是另一个博主写的很不错。
第二个就是在学习空间配置器的时候,必须要熟悉三种new。
template <class _Ty>
// plain new
inline _Ty* _allocate(ptrdiff_t size, _Ty*)
{
_Ty * tmp = (_Ty*)operator new((size_t)(size * sizeof(_Ty)));
if (tmp == nullptr)
{
std::cerr << "out of memory" << endl;
exit(1);
}
return tmp;
}
template<class _Ty>
// plain delete
inline void _deallocate(_Ty * buffer)
{
operator delete(buffer);
}
template <class T1, class T2>
//placement new
inline void _construct(T1 *p, const T2& value)
{
new((void *)p) T1(value);
}
template<class _Ty>
inline void _destroy(_Ty* ptr)
{
ptr ->~_Ty();
}
这是一个简单的空间配置的写法,可以看到这里面我标注了 plain new 和 placement new 两种。
现讲讲这两个new 是什么意思吧 第一个new就是可以理解成malloc(size * sizeof(_Ty)),没错,它的作用just 分配空间,返回的类型还需要和malloc一样进行强制类型转换。当然它还有种应用的位置,比如 int *p = new int[5]{0}; 就是我们普通的用法。
那第二个placement new 呢? 这个new的作用是定位并赋值。 这种 new 形式允许在一块已经分配成功的内存上重新构造对象或者对象数组。使用时不必担心失败,因为它根本就不会分配内存;使用它构造起来的对象,要显示的调用它们的析构函数,而不能使用 delete 。
下面在学习中还有一个,可能令人迷惑的地方
static void(* set_malloc_handler(void(*f)()))()
{
void(*old)() = _malloc_alloc_oom_handler;
_malloc_alloc_oom_handler = f;
return old;
}
看到这里 先不要急 你可以看到 这个函数被置为了0;然后
template<int inst>
void * _malloc_alloc_template<inst>::oom_malloc(size_t n)
{
void(*my_oom_handler)();
void * result;
//无限循环,直至成功分配内存或用户没有定制内存分配策略
for (;;)
{
my_oom_handler = _malloc_alloc_oom_handler;
if (my_oom_handler == nullptr)//如果用户没有定制内存分配策略
exit(1);
(*my_oom_handler)();//使用用户定制的方法
result = malloc(n);
if (result)
return result;
}
}
template<int inst>
void * _malloc_alloc_template<inst>::oom_realloc(void * p, size_t n)
{
//此函数的设计思路与oom_malloc如出一辙
void(*my_oom_handler)();
void * result;
for (;;)
{
my_oom_handler = _malloc_alloc_oom_handler;
if (my_oom_handler == nullptr)
exit(1);
(*my_oom_handler)();
result = realloc(p,n);
if (result)
return result;
}
}
然后你就可以明白,上面的代码的作用其实是写了一个自定义函数的接口,具体需要我们去实现它,如果我们没有本地策略去解决内存分配不足的问题的话。
那__malloc_alloc_oom_handler() = 0; 系统就会抛出异常,如果我们定义了一个函数,它会一直试图用这个函数去释放内存,在配置。