当前位置:编程学习 > C/C++ >>

基于策略模式的定制new和delete

背景
   在面向对象类的设计中,有时为了强化效能,特别是当构造大量小对象时,为了改善内存碎片,就需要自己实现对象的内存管理,以替换系统缺省的分配和释放行为,即全局的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继承。
 1template<class Alloc>
 2class new_delete_policy_base
 3{
 4public:
 5    static void* operator new(size_t size) throw (std::bad_alloc)
 6    { 
 7        void* ptr = Alloc::malloc(size);
 8        if(NULL==ptr) {
 9            throw std::bad_alloc();
10        }
11        return ptr;
12    }
13
14    static void* operator new(size_t size,void* ptr) throw()
15    { return ptr; }
16
17    static void* operator new(size_t size,const std::nothrow_t&) throw()
18    { return Alloc::malloc(size); }
19
20    static void operator delete(void* ptr) throw()
21    {  Alloc::free(ptr); }
22
23    static void operator delete(void* ptr, const std::nothrow_t&) throw()
24    {  Alloc::free(ptr); }
25
26    static void operator delete(void*, void*) throw()
27    { }
28
29    static void* operator new[](size_t size) throw(std::bad_alloc)
30    { return operator new (size); }
31   
32    static void* operator new[](size_t size,void* ptr) throw()
33    { return ptr; }
34
35    static void* operator new[](size_t size, const std::nothrow_t&) throw()
36    { return operator new (size, std::nothrow); }
37
38    static void operator delete[](void* ptr) throw()
39    {  operator delete (ptr); }
40
41    static void operator delete[](void* ptr, const std::nothrow_t&) throw()
42    { operator delete (ptr); }
43
44    static void operator delete[](void*, void*) throw()
45    { }
46};
47
48template<class Alloc>
49class object_pool_impl
50{
51public:
52    template<typename T>
53    static T* construct()
54    {
55        T* const p = static_cast<T*>(Alloc::malloc(sizeof(T)));
56        try { new (p) T(); }
57        catch(){ Alloc::free(p); throw; }
58        return p;
59    }
60
61    template<typename T>
62    static void destroy(T* const ptr)
63    {
64        ptr->~T();
65        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>继承,用于演示对象池构造和销毁对象的行为。
 1class quick_object : public new_delete_policy_base<mem_pool>
 2{
 3public:
 4    quick_object()
 5    {
 6#ifdef _THROW_EXCEPTION
 7        throw 0;
 8#endif
 9        cout << "quick_object()" << endl;   
10    }
11    ~quick_object()
12    {
13        cout << "~quick_object()" << endl;
14    }
15};
16
17class normal_object
18{
19public:
20    normal_object()
21    {
22        cout << "normal_object()" << endl;       
23    }
24    ~normal_object()
25    {
26        cout << "~normal_object()" << endl;
27    }
28};
29
30/**
31 *    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.
33 */
34static void unit_test_new_delete_policy()
35{   
36    quick_object* obj = NULL;
37
38    try {
39        obj = new quick_object; //call 易做图 new
40        delete obj;             //call 易做图 delete
41    }catch(){
42        //call 易做图 delete
43    }
44
45    try {
46        obj = new (std::nothrow) quick_object; //call nothrow new
47        delete obj; //call 易做图 delete
48    }catch(){
49        // call nothrow delete
50    }
51
52    try {
53        char ptr[sizeof(quick_object)];
54        obj = new (ptr) quick_object; //call placement new
55    }catch(){
56&nbs

补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,