vs2017 标准库中,std::allocator
的实现如下:
template<class _Ty>
class allocator
{
//...
void deallocate(_Ty * const _Ptr, const size_t _Count)
{ // deallocate object at _Ptr
// no overflow check on the following multiply; we assume _Allocate did that check
_Deallocate<_New_alignof<_Ty>>(_Ptr, sizeof(_Ty) * _Count);
}
_NODISCARD _DECLSPEC_ALLOCATOR _Ty * allocate(_CRT_GUARDOVERFLOW const size_t _Count)
{ // allocate array of _Count elements
return (static_cast<_Ty *>(_Allocate<_New_alignof<_Ty>>(_Get_size_of_n<sizeof(_Ty)>(_Count))));
}
}
allocator
是一个模板类,_Ty
用来指定给具体类分配内存。其中最重要的当然是 deallocate
和 allocate
两个函数,用来分配内存和释放内存。
先来看看 allocate
:
- 传入的参数为待分配内存对象的个数,而不是字节数。
- 底层的实现如下:
_DECLSPEC_ALLOCATOR static void * _Allocate(const size_t _Bytes)
{
return (::operator new(_Bytes));
}
可以看到,它并没有做任何内存管理的动作,只是调用了全局的 operator new
函数。
再来看看 deallocate
:
- 传入的参数为待释放内存块的指针,以及其中的放置对象的数量。
- 底层实现如下:
template<size_t _Align,
enable_if_t<(!_HAS_ALIGNED_NEW || _Align <= __STDCPP_DEFAULT_NEW_ALIGNMENT__), int> = 0> inline
void _Deallocate(void * _Ptr, size_t _Bytes)
{ // deallocate storage allocated by _Allocate when !_HAS_ALIGNED_NEW || _Align <= __STDCPP_DEFAULT_NEW_ALIGNMENT__
//...
::operator delete(_Ptr, _Bytes);
}
可以看到,它也只是调用了全局的 operator delete
函数。
因此,由上可以看出:
std::allocator
并没有做任何内存管理的动作,底层只是调用了::operator new
和::operator delete
,而它们又底层调用了malloc
和free
。所以,cookie 的内存浪费仍然存在。std::allocator
的内存分配和释放是以对象为单位,而不是字节。而且内存在释放的时候,还需要具体指定释放的内存块的大小(以对象为单位)。