DXUT11框架浅析(8)--CGrowableArray
CGrowableArray是一个模板类,实现了类似std::vector的数据结构。是一个基本数组,数据按顺序的依次存放。
1. 类的定义
template<typename TYPE> class CGrowableArray
{
public:
// 构造和销毁一个数组
CGrowableArray() { m_pData= NULL; m_nSize= 0; m_nMaxSize = 0; }
CGrowableArray(const CGrowableArray<TYPE>& a) { for( int i=0; i < a.m_nSize; i++ ) Add( a.m_pData[i] ); }
CGrowableArray& operator = ( constCGrowableArray<TYPE>&a )
{ if( this == &a ) return *this; RemoveAll(); for( int i=0; i < a.m_nSize; i++ ) Add( a.m_pData[i] ); return *this; }
~CGrowableArray(){ RemoveAll(); }
// 为数组增加元素
HRESULT Add( const TYPE& value);
HRESULT Insert( int nIndex, const TYPE& value);
HRESULT SetAt( int nIndex, const TYPE& value);
// 元素的个数
HRESULT SetSize( intnNewMaxSize );
int GetSize()const { return m_nSize; }
// 读取元素的值
const TYPE& operator[](int nIndex )const { return GetAt( nIndex); }
TYPE& operator[]( intnIndex ) { returnGetAt( nIndex); }
TYPE& GetAt( int nIndex ) const { assert( nIndex >= 0 && nIndex< m_nSize ); returnm_pData[nIndex];}
TYPE* GetData(){ return m_pData;}
// 搜索元素
int IndexOf(const TYPE&value ) { return( m_nSize > 0 ) ? IndexOf( value, 0, m_nSize ) : -1; }
int IndexOf(const TYPE&value, int iStart ) { return IndexOf( value,iStart, m_nSize- iStart ); }
int IndexOf(const TYPE&value, int nIndex, int nNumElements );
int LastIndexOf(const TYPE&value ) { return( m_nSize > 0 ) ? LastIndexOf( value, m_nSize-1, m_nSize) : -1; }
int LastIndexOf(const TYPE&value, int nIndex ) { return LastIndexOf( value,nIndex, nIndex+1); }
int LastIndexOf( constTYPE& value,int nIndex, int nNumElements);
bool Contains(const TYPE&value ){ return( -1 != IndexOf( value) ); }
// 清理元素或数组
HRESULT Remove( int nIndex );
void RemoveAll(){ SetSize(0); }
void Reset() { m_nSize = 0; }
protected:
// 指向存放实际数据的数组
TYPE* m_pData;
// 数组的元素个数
int m_nSize;
int m_nMaxSize; // max allocated
HRESULTSetSizeInternal( int nNewMaxSize ); // This versiondoesn't call ctor or dtor.
};
2. 主要成员方法
SetSizeInternal(…)检查缓冲区大小是否满足需要,如果不够用,则重建新的缓冲区
根据指定的数组成员个数nNewMaxSize,检查是否要重新分配内存。当然这个nNewMaxSize要求不能超过整形的最大值INT_MAX。
nNewMaxSize * sizeof( TYPE )便是所需分配的缓冲区内存大小(以字节为单位)。
如果需要重新分配内存,那么指向数组的m_pData指针和数组最多能存放元素个数的m_nMaxSize对象都要更新。
Add(…)在数组尾部添加一个新的元素
template<typename TYPE> HRESULT CGrowableArray <TYPE>::Add( const TYPE& value )
{
HRESULT hr;
// 检查缓冲区
if( FAILED( hr = SetSizeInternal( m_nSize + 1 ) ) )
return hr;
assert( m_pData != NULL );
// 创建一个新的TYPE*对象
::new ( &m_pData[m_nSize] ) TYPE;
// 将值赋给这个新建的对象,增加元素个数
m_pData[m_nSize] = value;
++m_nSize;
return S_OK;
}
Insert(…)在数组中间插入一个新的元素
template<typename TYPE> HRESULT CGrowableArray <TYPE>::Insert( int nIndex, const TYPE& value )
{
HRESULT hr;
// 检查传入的nIndex是否超出范围
if( nIndex < 0 ||
nIndex > m_nSize )
{
assert( false );
return E_INVALIDARG;
}
// 检查缓冲区
if( FAILED( hr = SetSizeInternal( m_nSize + 1 ) ) )
return hr;
// 移动内存
MoveMemory( &m_pData[nIndex + 1], &m_pData[nIndex], sizeof( TYPE ) * ( m_nSize - nIndex ) );
// 创建一个新的TYPE*对象
::new ( &m_pData[nIndex] ) TYPE;
//将值赋给这个新建的对象,增加元素个数
m_pData[nIndex] = value;
++m_nSize;
return S_OK;
}
IndexOf(…)
template<typename TYPE> int CGrowableArray <TYPE>::IndexOf( const TYPE& value, int iStart, int nNumElements )
{
// 检查传入的iStart和nNumElements是否有效
if( iStart < 0 ||
iStart >= m_nSize ||
nNumElements < 0 ||
iStart + nNumElements > m_nSize )
{
assert( false );
return -1;
}
// 遍历数组各个元素,查找满足value值的成员,如果找到,则记录index
for( int i = iStart; i < ( iStart + nNumElements ); i++ )
{
if( value == m_pData[i] )
return i;
}
// Not found
return -1;
}
3. 使用示例
CGrowableArray<int> m_TestList;
m_TestList.Add(3);
m_TestList.Add(5);
m_TestList.Add(7);
m_TestList.Add(9);
int nSize = m_TestList.GetSize();
int nIndex7 = m_TestList.IndexOf(7);
if( nIndex7 != -1 )
{
m_TestList.Remove(nIndex7);
}