CIntArray源码解析

(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;
};

CIntArray.cpp

/////////////////////////////////////////////////////////////////////////////
//
// 整理的微软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); 
}

/////////////////////////////////////////////////////////////////////////////



你可能感兴趣的:(数据结构)