C++primer中 CacheObj实现(非常有意思)
1 //CacheObj.h 2 3 #ifndef __CacheObj__ 4 #define __CacheObj__ 5 6 #include <iostream> 7 #include <stdexcept> 8 #include <malloc.h> 9 10 11 /* 12 * memory allocation class: Pre-allocates objects and 13 * maintains a freelist of objects that are unused 14 * When an object if freed, it is put back on the freelist 15 * some of the memory will be only returned when the program exist; 16 */ 17 template < typename Type > 18 class CacheObj 19 { 20 public: 21 static void* operator new(std::size_t); 22 #if 1 23 static void* operator new[](std::size_t); 24 #endif 25 26 static void operator delete(void*, std::size_t); 27 #if 1 28 static void operator delete[](void*, std::size_t); 29 #endif 30 31 virtual ~CacheObj(){} 32 33 protected: 34 Type *next; 35 static void list_free(void); 36 37 private: 38 static void add_to_freelist(Type *); 39 static Type* freelist; 40 static std::size_t unuse_size; //未用链表的长度不会超过2 * chunk; 41 static const std::size_t chunk; 42 }; 43 44 template < typename Type > Type* CacheObj< Type >::freelist = NULL; 45 template < typename Type > std::size_t CacheObj< Type >::unuse_size = 0; 46 template < typename Type > const std::size_t CacheObj< Type >::chunk = 2; 47 48 49 template < typename Type > 50 void* CacheObj< Type >::operator new(std::size_t size) 51 { 52 /* 53 * new should only be asked to build a Type; 54 * not an object derived from T; 55 * check that right size is requested 56 */ 57 if(size != sizeof(Type)) 58 { 59 throw std::runtime_error("CacheObj: wrong size object in operator new"); 60 } 61 62 63 //if list is empty: grab a new chunk of memory 64 //allocate allocates chunk number of objects of type Type 65 if(NULL == freelist) 66 { 67 #if 0 68 //一次申请大量数据空间,很爽啊,可是因为这种不计后果的行为,花费了大半天的时间 69 /*解释: 70 *很明显的bug例子:int *p = (int*)malloc(8*sizeof(int)); free(p); free(p+4); 71 *自己考虑的太不周全了 72 *使用一次性申请大量空间的bug出在: 73 * list_free()函数,其中每次free都以一个object的地址为参数,如同给出的bug示例,所以错了 74 * 75 */ 76 Type* array = (Type*)malloc(size * chunk); 77 if(NULL == array) 78 { 79 throw std::runtime_error("CacheObj: wrong size object in operator new"); 80 } 81 //谢谢陈涛,大神走了还有个人讨论,终于发现问题的所在了 82 #endif 83 84 //allocate allocates chunk number of objects of type T 85 for(unsigned int i = 0; i != chunk; i++) 86 { 87 #if 1 88 Type* array = (Type*)malloc(size); 89 if(NULL == array) 90 { 91 throw std::runtime_error("CacheObj: wrong size object in operator new"); 92 } 93 #endif 94 add_to_freelist(array); 95 #if 0 96 array++; 97 #endif 98 } 99 } 100 101 Type *p = freelist; 102 freelist = freelist->CacheObj< Type >::next; 103 unuse_size--; 104 p->CacheObj< Type >::next = NULL; 105 return p; 106 } 107 108 #if 1 109 template < typename Type > 110 void* CacheObj< Type >::operator new[](std::size_t size) 111 { 112 void *p = malloc(size); 113 return p; 114 } 115 #endif 116 117 template <typename Type > 118 void CacheObj< Type >::operator delete(void* p, std::size_t) 119 { 120 if(p != 0) 121 { 122 add_to_freelist(static_cast< Type* >(p)); 123 } 124 } 125 126 #if 1 127 template < typename Type > 128 void CacheObj< Type >::operator delete[](void* p, std::size_t) 129 { 130 if(!p) 131 free(p); 132 } 133 #endif 134 135 template < typename Type > 136 void CacheObj< Type >::list_free(void) 137 { 138 while(freelist) 139 { 140 Type *temp = freelist; 141 freelist = temp->CacheObj< Type >::next; 142 free(temp); 143 unuse_size--; 144 } 145 } 146 147 //puts object at head of the freelist 148 template < typename Type > 149 void CacheObj< Type >::add_to_freelist(Type *p) 150 { 151 if(!p) 152 return; 153 154 if(unuse_size >> 1 == chunk) 155 { 156 free(p); 157 return ; 158 } 159 160 unuse_size++; 161 p->CacheObj< Type >::next = freelist; 162 freelist = p; 163 } 164 165 #endif
//QueueItem.h #ifndef __QUEUEITEM__ #define __QUEUEITEM__ #include "CacheObj.h" template < typename Type > class Queue; //下面因为进行类模板特化,所以此处先声明 template < typename Type > std::ostream& operator<<(std::ostream&, const Queue< Type >&); //下面需要进行函数模特化,所以此处先声明 template < typename Type > class QueueItem: public CacheObj< QueueItem< Type > > { friend class Queue< Type >; //类模板特化 friend std::ostream& operator<< < Type >(std::ostream&, const Queue< Type >&); //函数模板特化 //private class : no public section; QueueItem(const Type &t): item(t), next(0){} Type item; //value stored in this element; QueueItem *next; //pointer to next element in the Queue; ~QueueItem(void) { next = NULL; } }; template < typename Type > class Queue { friend std::ostream& operator<< < Type >(std::ostream&, const Queue< Type >&); //函数模板特化 public: //empty Queue Queue(void):head(0), tail(0){} //copy control to manage pointers to QueueItems in the Queue Queue(const Queue &Q):head(0), tail(0) { copy_elems(Q); } template < typename Iter > Queue(Iter beg, Iter end); //成员模板 ~Queue(void); Queue& operator=(const Queue&); Type& front(void); const Type& front(void) const; //return element from head of Queue; void push(const Type&); //add element to back of Queue; void pop(void); //remove element from head of Queue; bool empty(void)const; //true if no elements in Queue; private: QueueItem< Type >* head; //pointer to first element in Queue; QueueItem< Type >* tail; //pointer to last element in Queue; //utility functions used by copy constructor, assignment, and destructor void destroy(void); //delete all the elements; void copy_elems(const Queue&); //copy elements from parameter template < typename Iter > void copy_elems(Iter beg, Iter end); //成员模板,且重载上一函数 }; //成员模板实现 template < typename Type > template < typename Iter > Queue< Type >::Queue(Iter beg, Iter end):head(0), tail(0) { destroy(); copy_elems(beg, end); } template < typename Type > Queue< Type >::~Queue(void) { destroy(); } template < typename Type > Queue< Type >& Queue< Type >::operator=(const Queue<Type>& src) { Queue< Type >* pt = head; if(head != 0) { while(pt) { QueueItem< Type >* temp = pt; pt = pt->next; delete temp; } } head = tail = 0; copy_elems(src); } template < typename Type > Type& Queue< Type >::front(void) { return head->item; } template < typename Type > const Type& Queue< Type >::front(void) const { return head->item; } template < typename Type > void Queue< Type >::push(const Type& val) { //allocate a new QueueItem object; QueueItem< Type >* pt = new QueueItem< Type >(val); //put item onto existing queue; if(empty()) { head = tail = pt; //the queue now has only one element; } else { tail->next = pt; //add new element to end of the queue; tail = pt; } } //pop is unchecked: Popping off an empty Queue is undefined; template < typename Type > void Queue< Type >::pop(void) { QueueItem< Type >* p = head; //keep pointer to head so we can delete it; head = head->next; //head now points to next element; delete p; //delete old head element; } template < typename Type > bool Queue< Type >::empty(void)const { return head == 0; } //成员函数实现 template < typename Type > void Queue< Type >::destroy(void) { while(!empty()) pop(); QueueItem< Type >::list_free(); } //copy elements from orig into this Queue; //loop stops when pt == 0, which happens when we reach orig.tail; template < typename Type > void Queue< Type >::copy_elems(const Queue< Type >& orig) { for(QueueItem< Type >*pt = orig.head; pt = pt->next;) { push(pt->item); } } //成员模板实现 template < typename Type > template < typename Iter > void Queue< Type >::copy_elems(Iter beg, Iter end) { while(beg != end) { push(*beg); ++beg; } } //普通函数模板 template < typename Type > std::ostream& operator<<(std::ostream &os, const Queue< Type >& q) { os << "< "; QueueItem< Type >*p; for(p = q.head; p ; p = p->next) { os << p->item << " "; } os << ">"; return os; } #endif
1 //test.cpp 2 3 #include <iostream> 4 #include "QueueItem.h" 5 6 int main(void) 7 { 8 int array[5] = {4, 6, 7, 8, 90}; 9 Queue<int> qi(array + 0, array + 5); 10 short s = 42; 11 qi.push(s); 12 qi.pop(); 13 qi.pop(); 14 qi.pop(); 15 qi.push(s); 16 qi.push(s); 17 std::cout << qi << std::endl; 18 19 return 0; 20 }