(1)MFC数组简介
MFC已经提供了各种各样的数组,首先是一般的CArray类,它实际上是一个模板类,利用它可以创建任何数据类型的“类型安全数组”。在头文件Afxtempl.h中定义了CArray。其次是非模板化的数组类,分别为保存特定类型的数组而设计。这些类在Afxcoll.h中定义,下面说明了非模板化的数组类以及它们所保存的数据类型:只要学会使用这些数组类中的一种,也就会用其它数组类了,因为它们共享公共的一组成员函数。
CByteArray 8位字节(BYTE)
CWordArray 16位字节(WORD)
CDWordArray 32位双字节(DWORD)
CUIntArray 无符号整型(UINT)
CStringArray CString
CObArray CObject指针
CPtrArray void指针
(2)CIntArray成员函数
(3)源码
CIntArray.h
class CUIntArray : public CObject
{
public:
// Construction
CUIntArray();
// Attributes
INT_PTR GetSize() const;
INT_PTR GetCount() const;
BOOL IsEmpty() const;
INT_PTR GetUpperBound() const;
void SetSize(INT_PTR nNewSize, INT_PTR nGrowBy = -1);
// Operations
// Clean up
void FreeExtra();
void RemoveAll();
// Accessing elements
UINT GetAt(INT_PTR nIndex) const;
void SetAt(INT_PTR nIndex, UINT newElement);
UINT& ElementAt(INT_PTR nIndex);
// Direct Access to the element data (may return NULL)
const UINT* GetData() const;
UINT* GetData();
// Potentially growing the array
void SetAtGrow(INT_PTR nIndex, UINT newElement);
INT_PTR Add(UINT newElement);
INT_PTR Append(const CUIntArray& src);
void Copy(const CUIntArray& src);
// overloaded operator helpers
UINT operator[](INT_PTR nIndex) const;
UINT& operator[](INT_PTR nIndex);
// Operations that move elements around
void InsertAt(INT_PTR nIndex, UINT newElement, INT_PTR nCount = 1);
void RemoveAt(INT_PTR nIndex, INT_PTR nCount = 1);
void InsertAt(INT_PTR nStartIndex, CUIntArray* pNewArray);
// Implementation
protected:
UINT* m_pData; // the actual array of data
INT_PTR m_nSize; // # of elements (upperBound - 1)
INT_PTR m_nMaxSize; // max allocated
INT_PTR m_nGrowBy; // grow amount
public:
~CUIntArray();
protected:
// local typedefs for class templates
typedef UINT BASE_TYPE;
typedef UINT BASE_ARG_TYPE;
};
/////////////////////////////////////////////////////////////////////////////
//
// 整理的微软CUIntArray源码,删除了部分功能(如Serialize/Dump/AssertValid等)
// Implementation of parameterized Array
//
/////////////////////////////////////////////////////////////////////////////
// NOTE: we allocate an array of 'm_nMaxSize' elements, but only
// the current size 'm_nSize' contains properly constructed
// objects.
#include "stdafx.h"
#include
#define new DEBUG_NEW
/////////////////////////////////////////////////////////////////////////////
CUIntArray::CUIntArray()
{
m_pData = NULL;
m_nSize = m_nMaxSize = m_nGrowBy = 0;
}
CUIntArray::~CUIntArray()
{
ASSERT_VALID(this);
delete[] (BYTE*)m_pData;
}
void CUIntArray::SetSize(INT_PTR nNewSize, INT_PTR nGrowBy)
{
ASSERT_VALID(this);
ASSERT(nNewSize >= 0);
if(nNewSize < 0 )
AfxThrowInvalidArgException();
if (nGrowBy >= 0)
m_nGrowBy = nGrowBy; // set new size
if (nNewSize == 0)
{
// shrink to nothing
delete[] (BYTE*)m_pData;
m_pData = NULL;
m_nSize = m_nMaxSize = 0;
}
else if (m_pData == NULL)
{
// create one with exact size
#ifdef SIZE_T_MAX
ASSERT(nNewSize <= SIZE_T_MAX/sizeof(UINT)); // no overflow
#endif
m_pData = (UINT*) new BYTE[nNewSize * sizeof(UINT)];
memset(m_pData, 0, nNewSize * sizeof(UINT)); // zero fill
m_nSize = m_nMaxSize = nNewSize;
}
else if (nNewSize <= m_nMaxSize)
{
// it fits
if (nNewSize > m_nSize)
{
// initialize the new elements
memset(&m_pData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(UINT));
}
m_nSize = nNewSize;
}
else
{
// otherwise, grow array
INT_PTR nGrowArrayBy = m_nGrowBy;
if (nGrowArrayBy == 0)
{
// heuristically determine growth when nGrowArrayBy == 0
// (this avoids heap fragmentation in many situations)
nGrowArrayBy = min(1024, max(4, m_nSize / 8));
}
INT_PTR nNewMax;
if (nNewSize < m_nMaxSize + nGrowArrayBy)
nNewMax = m_nMaxSize + nGrowArrayBy; // granularity
else
nNewMax = nNewSize; // no slush
ASSERT(nNewMax >= m_nMaxSize); // no wrap around
if(nNewMax < m_nMaxSize)
AfxThrowInvalidArgException();
#ifdef SIZE_T_MAX
ASSERT(nNewMax <= SIZE_T_MAX/sizeof(UINT)); // no overflow
#endif
UINT* pNewData = (UINT*) new BYTE[nNewMax * sizeof(UINT)];
// copy new data from old
Checked::memcpy_s(pNewData, nNewMax * sizeof(UINT),
m_pData, m_nSize * sizeof(UINT));
// construct remaining elements
ASSERT(nNewSize > m_nSize);
memset(&pNewData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(UINT));
// get rid of old stuff (note: no destructors called)
delete[] (BYTE*)m_pData;
m_pData = pNewData;
m_nSize = nNewSize;
m_nMaxSize = nNewMax;
}
}
INT_PTR CUIntArray::Append(const CUIntArray& src)
{
ASSERT_VALID(this);
ASSERT(this != &src); // cannot append to itself
if(this == &src)
AfxThrowInvalidArgException();
INT_PTR nOldSize = m_nSize;
SetSize(m_nSize + src.m_nSize);
Checked::memcpy_s(m_pData + nOldSize, src.m_nSize * sizeof(UINT),
src.m_pData, src.m_nSize * sizeof(UINT));
return nOldSize;
}
void CUIntArray::Copy(const CUIntArray& src)
{
ASSERT_VALID(this);
ASSERT(this != &src); // cannot append to itself
if(this != &src)
{
SetSize(src.m_nSize);
Checked::memcpy_s(m_pData, src.m_nSize * sizeof(UINT),
src.m_pData, src.m_nSize * sizeof(UINT));
}
}
void CUIntArray::FreeExtra()
{
ASSERT_VALID(this);
if (m_nSize != m_nMaxSize)
{
// shrink to desired size
#ifdef SIZE_T_MAX
ASSERT(m_nSize <= SIZE_T_MAX/sizeof(UINT)); // no overflow
#endif
UINT* pNewData = NULL;
if (m_nSize != 0)
{
pNewData = (UINT*) new BYTE[m_nSize * sizeof(UINT)];
// copy new data from old
Checked::memcpy_s(pNewData, m_nSize * sizeof(UINT),
m_pData, m_nSize * sizeof(UINT));
}
// get rid of old stuff (note: no destructors called)
delete[] (BYTE*)m_pData;
m_pData = pNewData;
m_nMaxSize = m_nSize;
}
}
/////////////////////////////////////////////////////////////////////////////
void CUIntArray::SetAtGrow(INT_PTR nIndex, UINT newElement)
{
ASSERT_VALID(this);
ASSERT(nIndex >= 0);
if(nIndex < 0)
AfxThrowInvalidArgException();
if (nIndex >= m_nSize)
SetSize(nIndex+1);
m_pData[nIndex] = newElement;
}
void CUIntArray::InsertAt(INT_PTR nIndex, UINT newElement, INT_PTR nCount)
{
ASSERT_VALID(this);
ASSERT(nIndex >= 0); // will expand to meet need
ASSERT(nCount > 0); // zero or negative size not allowed
if(nIndex < 0 || nCount <= 0)
AfxThrowInvalidArgException();
if (nIndex >= m_nSize)
{
// adding after the end of the array
SetSize(nIndex + nCount); // grow so nIndex is valid
}
else
{
// inserting in the middle of the array
INT_PTR nOldSize = m_nSize;
SetSize(m_nSize + nCount); // grow it to new size
// shift old data up to fill gap
Checked::memmove_s(&m_pData[nIndex+nCount], (m_nSize-(nIndex+nCount)) * sizeof(UINT),
&m_pData[nIndex], (nOldSize-nIndex) * sizeof(UINT));
// re-init slots we copied from
memset(&m_pData[nIndex], 0, nCount * sizeof(UINT));
}
// insert new value in the gap
ASSERT(nIndex + nCount <= m_nSize);
// copy elements into the empty space
while (nCount--)
m_pData[nIndex++] = newElement;
}
void CUIntArray::RemoveAt(INT_PTR nIndex, INT_PTR nCount)
{
ASSERT_VALID(this);
ASSERT(nIndex >= 0);
ASSERT(nCount >= 0);
INT_PTR nUpperBound = nIndex + nCount;
ASSERT(nUpperBound <= m_nSize && nUpperBound >= nIndex && nUpperBound >= nCount);
if(nIndex < 0 || nCount < 0 || (nUpperBound > m_nSize) || (nUpperBound < nIndex) || (nUpperBound < nCount))
AfxThrowInvalidArgException();
// just remove a range
INT_PTR nMoveCount = m_nSize - (nUpperBound);
if (nMoveCount)
{
Checked::memmove_s(&m_pData[nIndex], (size_t)nMoveCount * sizeof(UINT),
&m_pData[nUpperBound], (size_t)nMoveCount * sizeof(UINT));
}
m_nSize -= nCount;
}
void CUIntArray::InsertAt(INT_PTR nStartIndex, CUIntArray* pNewArray)
{
ASSERT_VALID(this);
ASSERT(pNewArray != NULL);
ASSERT_KINDOF(CUIntArray, pNewArray);
ASSERT_VALID(pNewArray);
ASSERT(nStartIndex >= 0);
if(pNewArray == NULL || nStartIndex < 0)
AfxThrowInvalidArgException();
if (pNewArray->GetSize() > 0)
{
InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize());
for (INT_PTR i = 0; i < pNewArray->GetSize(); i++)
SetAt(nStartIndex + i, pNewArray->GetAt(i));
}
}
INT_PTR CUIntArray::GetSize() const
{
return m_nSize;
}
INT_PTR CUIntArray::GetCount() const
{
return m_nSize;
}
BOOL CUIntArray::IsEmpty() const
{
return m_nSize == 0;
}
INT_PTR CUIntArray::GetUpperBound() const
{
return m_nSize-1;
}
void CUIntArray::RemoveAll()
{
SetSize(0);
}
UINT CUIntArray::GetAt(INT_PTR nIndex) const
{
ASSERT(nIndex >= 0 && nIndex < m_nSize);
if( nIndex < 0 || nIndex >= m_nSize )
AfxThrowInvalidArgException();
return m_pData[nIndex];
}
void CUIntArray::SetAt(INT_PTR nIndex, UINT newElement)
{
ASSERT(nIndex >= 0 && nIndex < m_nSize);
if( nIndex < 0 || nIndex >= m_nSize )
AfxThrowInvalidArgException();
m_pData[nIndex] = newElement;
}
UINT& CUIntArray::ElementAt(INT_PTR nIndex)
{
ASSERT(nIndex >= 0 && nIndex < m_nSize);
if( nIndex < 0 || nIndex >= m_nSize )
AfxThrowInvalidArgException();
return m_pData[nIndex];
}
const UINT* CUIntArray::GetData() const
{
return (const UINT*)m_pData;
}
UINT* CUIntArray::GetData()
{
return (UINT*)m_pData;
}
INT_PTR CUIntArray::Add(UINT newElement)
{
INT_PTR nIndex = m_nSize;
SetAtGrow(nIndex, newElement);
return nIndex;
}
UINT CUIntArray::operator[](INT_PTR nIndex) const
{
return GetAt(nIndex);
}
UINT& CUIntArray::operator[](INT_PTR nIndex)
{
return ElementAt(nIndex);
}
/////////////////////////////////////////////////////////////////////////////