一、C++对象创建的过程
比如以下的代码
class Foo{
};
Foo *pf = new Foo();//配置内存,然后构造对象
delete pf;//将对象析构,然后释放内存
new算式包含两个阶段
- 调用::operator new 配置内存。
- 调用Foo::Foo()构造对象的内容。
delete算式包含两个阶段
- 调用Foo::~Foo()将对象析构。
- 调用::operator delete 释放内存。
二、SGI标准的空间配置器 std::allocator
下面是SGI标准的空间配置器 std::allocator的源码,这里的allocator 只是基层内存配置/释放行为的一层简单的包装,并没有效率上的优化。
template <class T>
inline T* allocate(ptrdiff_t size, T*) {
set_new_handler(0);
T* tmp = (T*)(::operator new((size_t)(size * sizeof(T))));
if (tmp == 0) {
cerr << "out of memory" << endl;
exit(1);
}
return tmp;
}
template <class T>
inline void deallocate(T* buffer) {
::operator delete(buffer);
}
template <class 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;
pointer allocate(size_type n) {
return ::allocate((difference_type)n, (pointer)0);
}
void deallocate(pointer p) { ::deallocate(p); }
pointer address(reference x) { return (pointer)&x; }
const_pointer const_address(const_reference x) {
return (const_pointer)&x;
}
size_type init_page_size() {
return max(size_type(1), size_type(4096/sizeof(T)));
}
size_type max_size() const {
return max(size_type(1), size_type(UINT_MAX/sizeof(T)));
}
};
class allocator<void> {
public:
typedef void* pointer;
};
三、SGI特殊的空间配置器 std::alloc
STL allocator将new算式以及delete算式的两个阶段的操作分开。内存配置操作由alloc::allocate()负责,内存释放由alloc::deallocate()负责;对象构造由::construct()负责,对象析构由::destrory()负责。
空间配置器的包装类simple_alloc
- 可指定配置一级或者二级空间配置器
template<class T, class Alloc>
class simple_alloc {
public:
static T *allocate(size_t n)
{ return 0 == n? 0 : (T*) Alloc::allocate(n * sizeof (T)); }
static T *allocate(void)
{ return (T*) Alloc::allocate(sizeof (T)); }
static void deallocate(T *p, size_t n)
{ if (0 != n) Alloc::deallocate(p, n * sizeof (T)); }
static void deallocate(T *p)
{ Alloc::deallocate(p, sizeof (T)); }
};
一级空间配置器源码
template <int inst>
class __malloc_alloc_template
{
private:
static void *oom_malloc(size_t);
static void *oom_realloc(void *, size_t);
#ifndef __STL_STATIC_TEMPLATE_MEMBER_BUG
static void (* __malloc_alloc_oom_handler)(); //当前的内存分配失败处理例程
#endif
public:
static void * allocate(size_t n)
{
void *result = malloc(n);
//分配内存失败,调用oom_malloc尝试分配所需内存
if (0 == result)
result = oom_malloc(n);
return result;
}
static void deallocate(void *p, size_t /* n */)
{
free(p);
}
static void * reallocate(void *p, size_t /* old_sz */, size_t new_sz)
{
void * result = realloc(p, new_sz);
//分配内存失败,调用oom_realloc尝试分配所需内存
if (0 == result)
result = oom_realloc(p, new_sz);
return result;
}
//模拟C++标准的std::set_new_handle全局函数设置内存分配失败后的处理例程
static void (* set_malloc_handler(void (*f)()))()
{
//保存旧的处理例程
void (* old)() = __malloc_alloc_oom_handler;
//设置新的处理例程
__malloc_alloc_oom_handler = f;
//返回旧的处理例程
return(old);
}
};
// malloc_alloc out-of-memory handling
#ifndef __STL_STATIC_TEMPLATE_MEMBER_BUG
template <int inst>
void (* __malloc_alloc_template<inst>::__malloc_alloc_oom_handler)() = 0;
#endif
template <int inst>
void * __malloc_alloc_template<inst>::oom_malloc(size_t n)
{
void (* my_malloc_handler)();
void *result;
//此循环只在两种情形下才会返回
//1. 没有设置内存分配失败后的处理例程
//2. 重新利用malloc尝试分配内存成功
for (;;)
{
my_malloc_handler = __malloc_alloc_oom_handler;
if (0 == my_malloc_handler)
{
__THROW_BAD_ALLOC;
}
(*my_malloc_handler)(); //调用内存分配失败后设置的处理例程,参见Effective C++
result = malloc(n);
if (result)
return(result);
}
}
template <int inst>
void * __malloc_alloc_template<inst>::oom_realloc(void *p, size_t n)
{
void (* my_malloc_handler)();
void *result;
for (;;)
{
my_malloc_handler = __malloc_alloc_oom_handler;
if (0 == my_malloc_handler)
{
__THROW_BAD_ALLOC;
}
(*my_malloc_handler)();
result = realloc(p, n);
if (result)
return(result);
}
}
typedef __malloc_alloc_template<0> malloc_alloc;
二级空间配置器源码
https://blog.csdn.net/wenqian1991/article/details/19605727
https://blog.csdn.net/dandelion_gong/article/details/51353918
参考
《C++ 内存分配(new,operator new)详解)》
https://blog.csdn.net/wudaijun/article/details/9273339
网友评论