對象池的指針版本。池中本質上是一群對象,只構造一次,返回指針。主要支持頻繁重建的內存空間不連續的自建結構,如樹,鏈表。

/**//******************************************************************
*名稱:PointerPool(指針池)(模板)
*版本號:0.1
*作者:趙耀(中山大學2010級)
*時間:2011.4.11
*簡介:
* 對應于對象池,這是一個指針池,用于緩存頻繁調用的指針(對象).主要支
* 持頻繁重建的樹或鏈表等結構.具有默認構造函數接收一個size_t對象表明指針
* 分塊的大小,默認為10.接收的參數如果<=0則會拋出異常invalid_argument.
* public方法:
* T* getPointer(); 從池中返回一個該類型對象的指針;
* void recyclePointer( T* ); 接受需要回收的指針;
* void clear(); 清空池以釋放占用的內存;
* bool empty(); 返回池是否為空;
* size_t size(); 返回池中總指針數量;
* size_t remain(); 返回指針池剩余可用指針的數量;
* 注意:
* 使用方法可簡單地想成通過兩個成員函數來代替new和delete.必須確保分
* 配的指針得到回收!必須確保回收的指針不是外來指針!因為未進行二次初始化,
* 重新分配得到的指針所指對象可能是上一次使用后的殘余對象,請進行必要的初
* 話工作.
*
*未完成特性:
* 因為主要支持樹,鏈表等內存空間不連續的結構,所以未實現成數組規模
* 地分配指針的功能.
*
*已知bug:暫無
*
*版權信息:
* 該代碼為開源代碼,原作者保留其所有權.你可以拷貝,修改,使用該代碼,但
* 是請保留必要的版權信息.
******************************************************************/
#ifndef POINTERPOOL_H
#define POINTERPOOL_H

#include <vector>
#include <queue>
#include <stdexcept>
#include <memory>
using namespace std;

template< typename T >
class PointerPool


{
public:
//Create a PointerPool to contain size pointers.
PointerPool( size_t size = kDefaultChunkSize )
throw ( invalid_argument, bad_alloc );
~PointerPool();

//Return a specific pointer to client.
T *getPointer();
//Recycle the pointer that the client doesn't need any more.
void recyclePointer( T* );
//Clear the pool and release the memory.
void clear();
bool empty();
//Return the total number of pointers the pool contains.
size_t size();
//Return the number of pointers remain available.
size_t remain();

protected:
queue< T* > mFreeList;
vector< T* > mAllpointers;//A record of all pointers which help
//to destroy them.

size_t mChunkSize;
static const size_t kDefaultChunkSize = 10;

//Allocate mChunkSize new pointers and add them to the
//mFreeList.
void allocateChunk();
//help the destructor the delete the pointers int the pool.
static void deleteHelper( T* );

private:
//Hide the copy constructor and assignment symbol.
PointerPool( const PointerPool< T > & );
PointerPool< T > &operator=( const PointerPool< T > & );
};

template< typename T >
size_t PointerPool<T>::remain()


{
return mFreeList.size();
}

template< typename T >
bool PointerPool<T>::empty()


{
return remain() == 0;
}

template< typename T >
size_t PointerPool<T>::size()


{
return mChunkSize * mAllpointers.size();
}

template< typename T >

PointerPool<T>::PointerPool( size_t size /**//*= kDefaultChunkSize */ ) throw ( invalid_argument, bad_alloc )


{
if ( size <= 0 )
throw invalid_argument( "chunk size must be positive" );

mChunkSize = size;
allocateChunk();
}

template< typename T >
T *PointerPool<T>::getPointer()


{
if ( mFreeList.empty() )
allocateChunk();

T *ptr = mFreeList.front();
mFreeList.pop();
return ptr;
}

template< typename T >
void PointerPool<T>::clear()


{
for_each( mAllpointers.begin(), mAllpointers.end(), deleteHelper );

mAllpointers.clear();
while ( !mFreeList.empty() )
mFreeList.pop();
}

template< typename T >
void PointerPool<T>::recyclePointer( T *ptr )


{
mFreeList.push( ptr );
}

template< typename T >
void PointerPool<T>::allocateChunk()


{
T* newPointerChunk = new T[ mChunkSize ];

mAllpointers.push_back( newPointerChunk );
for ( int i = 0; i < mChunkSize; i++ )

{
mFreeList.push( &newPointerChunk[i] );
}
}

template< typename T >
void PointerPool<T>::deleteHelper( T *pointerChunk )


{
delete [] pointerChunk;
}

template< typename T >
PointerPool<T>::~PointerPool()


{
for_each( mAllpointers.begin(), mAllpointers.end(), deleteHelper );
}

#endif
以下為測試代碼:
#include "PointerPool.h"
#include <iostream>
using namespace std;

class ListNode


{
public:
int value;
ListNode *nextPtr;

ListNode() : value(0), nextPtr(0)

{}
};

int growing()


{
static int numGrouwing = 0;
return numGrouwing++;
}

int main()


{
const int cases = 2;
PointerPool< ListNode > lnPool;

//Make 2 tests.
for ( int i = 0; i < cases; i++ )

{
if ( lnPool.empty() )
cout << "The pool is empty!" << endl;
else
cout << "The pool has " << lnPool.remain()
<< " pointers available" << endl;

//Create the head of a list.
ListNode *start = lnPool.getPointer();
start->value = growing();
ListNode *last = start;

//Complete the list with length of 100.
for ( int j = 1; j < 100; j++ )

{
ListNode *tmp = lnPool.getPointer();
tmp->value = growing();
last->nextPtr = tmp;
last = tmp;
}

//Travel and cout the value of each node.
ListNode *current = start;
while ( current != 0 )

{
cout << current->value << '\t';
current = current->nextPtr;
}

//Recycle all pointers back to the pool.
while ( start != 0 )

{
current = start;
start = start->nextPtr;
lnPool.recyclePointer( current );
}

cout << "The pool has " << lnPool.size() << " pointers"
<< "\n\n";
//Try clear the pool
lnPool.clear();
}
}