引言
   在面向对象类的设计中,有时为了强化效能,特别是当构造大量小对象时,为了改善内存碎片,就需要自己实现对象的内存管理,以替换系统缺省的分配和释放行为,即全局的new和delete。按照c++标准,在定制类专属的new和delete时,为了减免客户代码使用时的麻烦和问题,需要考虑同时定制
简单(normal new)、
定位(placement new)和
无异常(nothrow new)三种new情形,以及与之配对的
三种delete情形,另外还有对应的
数组new[]和delete[]各三种情形。在接口设计上,每种情形都是operator new和operator delete的重载版本;在内存管理上,具体的对象空间分配和释放是灵活的,因此这一部分可实现为策略模式,通过改变替换不同的内存管理策略,即可轻易获得不同的内存分配和释放行为,而类的代码则无须改变。为了方便定制类的new和delete,可以从一个接口基类模板继承而自动获得这种特性。这个基类模板实现了单个对象的new、delete和对象数组的new、delete,而模板参数正是内存管理策略类,它的设计约束如下:
   1)必须存在static成员方法
malloc和
free,其参数和返回值与C库的malloc和free一致。
   2)malloc只分配空间,若分配成功则不必初始化,否则失败返回NULL,不能抛出异常,因为normal new的语义为对于分配失败则抛出std::bad_alloc异常,而nothrow new则返回NULL,如此两种方式兼备,有利于客户代码的按需灵活检测;free只释放或归还空间。
   3)malloc和free的内部实现是灵活的,由应用开发者定制。
组件
   这里实现了
new_delete_policy_base和
object_pool_impl两个基础组件,代码如下,前者是支持内存管理策略的定制new和delete接口基类模板,从该类继承的子类其对象的构造和析构就被定制了;后者是支持内存管理策略的非侵入式对象池类模板,可直接用于构造某类的对象,包括内建的基本数据类型,而该类不必从new_delete_policy_base继承。
 1 template<class Alloc>
template<class Alloc>
 2 class new_delete_policy_base
class new_delete_policy_base
 3

 {
{
 4 public:
public:
 5 static void* operator new(size_t size) throw (std::bad_alloc)
    static void* operator new(size_t size) throw (std::bad_alloc)
 6
 
     {
{  
 7 void* ptr = Alloc::malloc(size);
        void* ptr = Alloc::malloc(size);
 8
 if(NULL==ptr)
        if(NULL==ptr)  {
{
 9 throw std::bad_alloc();
            throw std::bad_alloc();
10 }
        }
11 return ptr;
        return ptr;
12 }
    }
13
14 static void* operator new(size_t size,void* ptr) throw()
    static void* operator new(size_t size,void* ptr) throw()
15
 
     { return ptr; }
{ return ptr; }
16
17 static void* operator new(size_t size,const std::nothrow_t&) throw()
    static void* operator new(size_t size,const std::nothrow_t&) throw()
18
 
     { return Alloc::malloc(size); }
{ return Alloc::malloc(size); }
19
20 static void operator delete(void* ptr) throw()
    static void operator delete(void* ptr) throw()
21
 
     {  Alloc::free(ptr); }
{  Alloc::free(ptr); }
22
23 static void operator delete(void* ptr, const std::nothrow_t&) throw()
    static void operator delete(void* ptr, const std::nothrow_t&) throw()
24
 
     {  Alloc::free(ptr); }
{  Alloc::free(ptr); }
25
26 static void operator delete(void*, void*) throw()
    static void operator delete(void*, void*) throw()
27
 
     { }
{ }
28
29 static void* operator new[](size_t size) throw(std::bad_alloc)
    static void* operator new[](size_t size) throw(std::bad_alloc)
30
 
     { return operator new (size); }
{ return operator new (size); }
31 
    
32 static void* operator new[](size_t size,void* ptr) throw()
    static void* operator new[](size_t size,void* ptr) throw()
33
 
     { return ptr; }
{ return ptr; }
34
35 static void* operator new[](size_t size, const std::nothrow_t&) throw()
    static void* operator new[](size_t size, const std::nothrow_t&) throw()
36
 
     { return operator new (size, std::nothrow); }
{ return operator new (size, std::nothrow); }
37
38 static void operator delete[](void* ptr) throw()
    static void operator delete[](void* ptr) throw()
39
 
     {  operator delete (ptr); }
{  operator delete (ptr); }
40
41 static void operator delete[](void* ptr, const std::nothrow_t&) throw()
    static void operator delete[](void* ptr, const std::nothrow_t&) throw()
42
 
     { operator delete (ptr); }
{ operator delete (ptr); }
43
44 static void operator delete[](void*, void*) throw()
    static void operator delete[](void*, void*) throw()
45
 
     { }
{ }
46 };
};
47
48 template<class Alloc>
template<class Alloc>
49 class object_pool_impl
class object_pool_impl
50

 {
{
51 public:
public:
52 template<typename T>
    template<typename T>
53 static T* construct()
    static T* construct() 
54
 
     {
{
55 T* const p = static_cast<T*>(Alloc::malloc(sizeof(T)));
        T* const p = static_cast<T*>(Alloc::malloc(sizeof(T)));
56
 try
        try  { new (p) T(); }
{ new (p) T(); }
57
 catch(
        catch( )
) { Alloc::free(p); throw; }
{ Alloc::free(p); throw; }
58 return p;
        return p;
59 }
    }
60
61 template<typename T>
    template<typename T>
62 static void destroy(T* const ptr)
    static void destroy(T* const ptr)
63
 
     {
{
64 ptr->~T();
        ptr->~T();
65 Alloc::free(ptr);
        Alloc::free(ptr);
66 }
    }
67 };
}; 
 
 
应用
   下面代码中的mem_pool是一种基于自由列表机制实现的内存池,quick_object从new_delete_policy_base<mem_pool>继承,用于演示定制new和delete的行为,_THROW_EXCEPTION宏用于屏蔽代码,测试当对象空间分配成功但构造函数抛出异常时,对应的operator delete是否得到调用,而保证释放内存空间,normal_object是空类,它不从new_delete_policy_base<mem_pool>继承,用于演示对象池构造和销毁对象的行为。
 1 class quick_object : public new_delete_policy_base<mem_pool>
class quick_object : public new_delete_policy_base<mem_pool>
 2

 {
{
 3 public:
public:
 4 quick_object()
    quick_object() 
 5
 
     {
{
 6 #ifdef _THROW_EXCEPTION
#ifdef _THROW_EXCEPTION
 7 throw 0;
        throw 0;
 8 #endif
#endif
 9 cout << "quick_object()" << endl;
        cout << "quick_object()" << endl;    
10 }
    }
11 ~quick_object()
    ~quick_object()
12
 
     {
{
13 cout << "~quick_object()" << endl;
        cout << "~quick_object()" << endl;
14 }
    }
15 };
};
16
17 class normal_object
class normal_object
18

 {
{
19 public:
public:
20 normal_object()
    normal_object() 
21
 
     {
{
22 cout << "normal_object()" << endl;
        cout << "normal_object()" << endl;        
23 }
    }
24 ~normal_object()
    ~normal_object()
25
 
     {
{
26 cout << "~normal_object()" << endl;
        cout << "~normal_object()" << endl;
27 }
    }
28 };
};
29
30 /**
/**
31 *    the following code,if quick_object's construct function throw exception,then result in
 *    the following code,if quick_object's construct function throw exception,then result in
32 *    c/c++ Run-time system call operator delete correspond to operator new automaticlly.
 *    c/c++ Run-time system call operator delete correspond to operator new automaticlly.
33 */
 */
34 static void unit_test_new_delete_policy()
static void unit_test_new_delete_policy()
35

 {
{    
36 quick_object* obj = NULL;
    quick_object* obj = NULL;
37
38
 try
    try  {
{
39 obj = new quick_object; //call simple new
        obj = new quick_object; //call simple new
40 delete obj;             //call simple delete
        delete obj;             //call simple delete
41
 }catch(
    }catch( )
) {
{
42 //call simple delete
        //call simple delete
43 }
    }
44
45
 try
    try  {
{
46 obj = new (std::nothrow) quick_object; //call nothrow new
        obj = new (std::nothrow) quick_object; //call nothrow new
47 delete obj; //call simple delete
        delete obj; //call simple delete
48
 }catch(
    }catch( )
) {
{
49 // call nothrow delete
        // call nothrow delete
50 }
    }
51
52
 try
    try  {
{
53 char ptr[sizeof(quick_object)];
        char ptr[sizeof(quick_object)];
54 obj = new (ptr) quick_object; //call placement new
        obj = new (ptr) quick_object; //call placement new
55
 }catch(
    }catch( )
) {
{
56 //call placement delete
        //call placement delete
57 }
    }
58 
    
59
 try
    try {
{
60 obj = new quick_object[10]; //call simple new[]
        obj = new quick_object[10]; //call simple new[]
61 delete []obj;        //call simple delete[]
        delete []obj;        //call simple delete[]
62
 }catch(
    }catch( )
) {
{
63 //call simple delete[]
        //call simple delete[]
64 }
    }
65
66
 try
    try  {
{
67 obj = new (std::nothrow) quick_object[10]; //call nothrow new[]
        obj = new (std::nothrow) quick_object[10]; //call nothrow new[]
68 delete []obj; //call simple delete[]
        delete []obj; //call simple delete[]
69
 }catch(
    }catch( )
) {
{
70 //call nothrow delete[]
        //call nothrow delete[]
71 }
    }
72
73
 try
    try  {
{
74 char ptr[sizeof(quick_object[10])];
        char ptr[sizeof(quick_object[10])];
75 obj = new (ptr) quick_object[10];    //call placement new[]
        obj = new (ptr) quick_object[10];    //call placement new[]
76
 }catch (
    }catch ( )
)  {
{
77 //call placement delete[]
        //call placement delete[]
78 }
    }
79 }
}
80
81 /**
/**
82 *    class quick_object is inherited from class new_delete_policy_base<mem_pool> that has implement
 *    class quick_object is inherited from class new_delete_policy_base<mem_pool> that has implement 
83 *    operator new and delete,so that call placement new in template member construct of class obj_pool.
 *    operator new and delete,so that call placement new in template member construct of class obj_pool.
84 */
 */
85 static void unit_test_obj_pool()
static void unit_test_obj_pool()
86

 {
{
87 typedef object_pool_impl<mem_pool> obj_pool;
    typedef object_pool_impl<mem_pool> obj_pool;
88
89
 try
    try {
{
90 quick_object* obj = obj_pool::construct<quick_object>();
        quick_object* obj = obj_pool::construct<quick_object>();
91 obj_pool::destroy(obj);
        obj_pool::destroy(obj);
92
 }catch (
    }catch ( )
)  {
{
93
94 }
    }
95 //class normal_object's construct function do not throw exception.
    //class normal_object's construct function do not throw exception.
96 normal_object* obj = obj_pool::construct<normal_object>();
    normal_object* obj = obj_pool::construct<normal_object>();
97 obj_pool::destroy(obj);
    obj_pool::destroy(obj);
98 }
} 
 
 
	posted on 2012-09-27 17:37 
春秋十二月 阅读(2101) 
评论(2)  编辑 收藏 引用  所属分类: 
C/C++