對(duì)象池的指針版本。池中本質(zhì)上是一群對(duì)象,只構(gòu)造一次,返回指針。主要支持頻繁重建的內(nèi)存空間不連續(xù)的自建結(jié)構(gòu),如樹(shù),鏈表。

/**//******************************************************************
*名稱(chēng):PointerPool(指針池)(模板)
*版本號(hào):0.1
*作者:趙耀(中山大學(xué)2010級(jí))
*時(shí)間:2011.4.11
*簡(jiǎn)介:
* 對(duì)應(yīng)于對(duì)象池,這是一個(gè)指針池,用于緩存頻繁調(diào)用的指針(對(duì)象).主要支
* 持頻繁重建的樹(shù)或鏈表等結(jié)構(gòu).具有默認(rèn)構(gòu)造函數(shù)接收一個(gè)size_t對(duì)象表明指針
* 分塊的大小,默認(rèn)為10.接收的參數(shù)如果<=0則會(huì)拋出異常invalid_argument.
* public方法:
* T* getPointer(); 從池中返回一個(gè)該類(lèi)型對(duì)象的指針;
* void recyclePointer( T* ); 接受需要回收的指針;
* void clear(); 清空池以釋放占用的內(nèi)存;
* bool empty(); 返回池是否為空;
* size_t size(); 返回池中總指針數(shù)量;
* size_t remain(); 返回指針池剩余可用指針的數(shù)量;
* 注意:
* 使用方法可簡(jiǎn)單地想成通過(guò)兩個(gè)成員函數(shù)來(lái)代替new和delete.必須確保分
* 配的指針得到回收!必須確保回收的指針不是外來(lái)指針!因?yàn)槲催M(jìn)行二次初始化,
* 重新分配得到的指針?biāo)笇?duì)象可能是上一次使用后的殘余對(duì)象,請(qǐng)進(jìn)行必要的初
* 話(huà)工作.
*
*未完成特性:
* 因?yàn)橹饕С謽?shù),鏈表等內(nèi)存空間不連續(xù)的結(jié)構(gòu),所以未實(shí)現(xiàn)成數(shù)組規(guī)模
* 地分配指針的功能.
*
*已知bug:暫無(wú)
*
*版權(quán)信息:
* 該代碼為開(kāi)源代碼,原作者保留其所有權(quán).你可以拷貝,修改,使用該代碼,但
* 是請(qǐng)保留必要的版權(quán)信息.
******************************************************************/
#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
以下為測(cè)試代碼:
#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();
}
}