/ // CArray<TYPE, ARG_TYPE> template<class TYPE, class ARG_TYPE = const TYPE&> class CArray : public CObject { public: // Construction CArray(); // Attributes INT_PTR GetSize() const; // return m_nSize; INT_PTR GetCount() const; // return m_nSize; BOOL IsEmpty() const; // return m_nSize == 0; INT_PTR GetUpperBound() const; // return m_nSize-1; void SetSize(INT_PTR nNewSize, INT_PTR nGrowBy = -1); // Operations // Clean up void FreeExtra(); void RemoveAll(); // SetSize(0, -1); // Accessing elements const TYPE& GetAt(INT_PTR nIndex) const; TYPE& GetAt(INT_PTR nIndex); void SetAt(INT_PTR nIndex, ARG_TYPE newElement); const TYPE& ElementAt(INT_PTR nIndex) const; TYPE& ElementAt(INT_PTR nIndex); // Direct Access to the element data (may return NULL) const TYPE* GetData() const; TYPE* GetData(); // Potentially growing the array void SetAtGrow(INT_PTR nIndex, ARG_TYPE newElement); INT_PTR Add(ARG_TYPE newElement); // 数组末尾添加元素 INT_PTR Append(const CArray& src); // 数组末尾添加数组 void Copy(const CArray& src); // 拷贝数组 // overloaded operator helpers const TYPE& operator[](INT_PTR nIndex) const; TYPE& operator[](INT_PTR nIndex); // Operations that move elements around void InsertAt(INT_PTR nIndex, ARG_TYPE newElement, INT_PTR nCount = 1); void RemoveAt(INT_PTR nIndex, INT_PTR nCount = 1); void InsertAt(INT_PTR nStartIndex, CArray* pNewArray); // Implementation protected: TYPE* m_pData; // 指向数组内存区的指针 INT_PTR m_nSize; // 元素个数 INT_PTR m_nMaxSize; // 最大元素个数 INT_PTR m_nGrowBy; // 增长量 public: ~CArray(); void Serialize(CArchive&); #ifdef _DEBUG void Dump(CDumpContext&) const; void AssertValid() const; #endif }; SetSize函数 template<class TYPE, class ARG_TYPE> void CArray<TYPE, ARG_TYPE>::SetSize(INT_PTR nNewSize, INT_PTR nGrowBy) { if(nNewSize < 0 ) AfxThrowInvalidArgException(); if (nGrowBy >= 0) m_nGrowBy = nGrowBy; // set new size if (nNewSize == 0) // 1、新元素个数为0,清空数组 { // shrink to nothing if (m_pData != NULL) { for( int i = 0; i < m_nSize; i++ ) (m_pData + i)->~TYPE(); // 调用每个元素的析构函数,析构数据 delete[] (BYTE*)m_pData; m_pData = NULL; } m_nSize = m_nMaxSize = 0; } else if (m_pData == NULL) // 2、还没有分配数组空间 { // create buffer big enough to hold number of requested elements or // m_nGrowBy elements, whichever is larger. size_t nAllocSize = __max(nNewSize, m_nGrowBy); m_pData = (TYPE*) new BYTE[(size_t)nAllocSize * sizeof(TYPE)]; memset((void*)m_pData, 0, (size_t)nAllocSize * sizeof(TYPE)); for( int i = 0; i < nNewSize; i++ ) ::new( (void*)( m_pData + i ) ) TYPE; // 在指定内存位置创建 m_nSize = nNewSize; m_nMaxSize = nAllocSize; } else if (nNewSize <= m_nMaxSize) // 3、新元素个数小于最大元素个数,不需重新分配内存 { // it fits if (nNewSize > m_nSize) { // initialize the new elements memset((void*)(m_pData + m_nSize), 0, (size_t)(nNewSize-m_nSize) * sizeof(TYPE)); for( int i = 0; i < nNewSize-m_nSize; i++ ) ::new( (void*)( m_pData + m_nSize + i ) ) TYPE; } else if (m_nSize > nNewSize) { // destroy the old elements for( int i = 0; i < m_nSize-nNewSize; i++ ) (m_pData + nNewSize + i)->~TYPE(); } m_nSize = nNewSize; } else // 4、新元素个数大于最大元素个数,需要重新分配内存 { // otherwise, grow array nGrowBy = m_nGrowBy; if (nGrowBy == 0) { // heuristically determine growth when nGrowBy == 0 // (this avoids heap fragmentation in many situations) nGrowBy = m_nSize / 8; nGrowBy = (nGrowBy < 4) ? 4 : ((nGrowBy > 1024) ? 1024 : nGrowBy); } INT_PTR nNewMax; if (nNewSize < m_nMaxSize + nGrowBy) nNewMax = m_nMaxSize + nGrowBy; // granularity else nNewMax = nNewSize; // no slush if(nNewMax < m_nMaxSize) AfxThrowInvalidArgException(); TYPE* pNewData = (TYPE*) new BYTE[(size_t)nNewMax * sizeof(TYPE)]; // copy new data from old ::ATL::Checked::memcpy_s(pNewData, (size_t)nNewMax * sizeof(TYPE), m_pData, (size_t)m_nSize * sizeof(TYPE)); // construct remaining elements memset((void*)(pNewData + m_nSize), 0, (size_t)(nNewSize-m_nSize) * sizeof(TYPE)); for( int i = 0; i < nNewSize-m_nSize; i++ ) ::new( (void*)( pNewData + m_nSize + i ) ) TYPE; // get rid of old stuff (note: no destructors called) delete[] (BYTE*)m_pData; m_pData = pNewData; m_nSize = nNewSize; m_nMaxSize = nNewMax; } } FreeExtra函数 template<class TYPE, class ARG_TYPE> void CArray<TYPE, ARG_TYPE>::FreeExtra() // 释放多余内存 { if (m_nSize != m_nMaxSize) { // shrink to desired size TYPE* pNewData = NULL; if (m_nSize != 0) { pNewData = (TYPE*) new BYTE[m_nSize * sizeof(TYPE)]; // copy new data from old ::ATL::Checked::memcpy_s(pNewData, m_nSize * sizeof(TYPE), m_pData, m_nSize * sizeof(TYPE)); } // get rid of old stuff (note: no destructors called) delete[] (BYTE*)m_pData; m_pData = pNewData; m_nMaxSize = m_nSize; } } SetAtGrow函数 // 设置nIndex的值为newElement,nIndex可以大于当前数组最大下标 template<class TYPE, class ARG_TYPE> void CArray<TYPE, ARG_TYPE>::SetAtGrow(INT_PTR nIndex, ARG_TYPE newElement) { if(nIndex < 0) AfxThrowInvalidArgException(); if (nIndex >= m_nSize) SetSize(nIndex+1, -1); // 如果nIndex大于m_nSize,先增长空间 m_pData[nIndex] = newElement; } Add和Append函数 // 在数组末尾插入值为newElement的元素 INT_PTR CArray<TYPE, ARG_TYPE>::Add(ARG_TYPE newElement) { INT_PTR nIndex = m_nSize; SetAtGrow(nIndex, newElement); return nIndex; } // 在数组末尾插入数组src中的元素 template<class TYPE, class ARG_TYPE> INT_PTR CArray<TYPE, ARG_TYPE>::Append(const CArray& src) { if(this == &src) AfxThrowInvalidArgException(); INT_PTR nOldSize = m_nSize; SetSize(m_nSize + src.m_nSize); CopyElements<TYPE>(m_pData + nOldSize, src.m_pData, src.m_nSize); return nOldSize; } Copy函数 // 拷贝数组元素 template<class TYPE, class ARG_TYPE> void CArray<TYPE, ARG_TYPE>::Copy(const CArray& src) { if(this != &src) { SetSize(src.m_nSize); CopyElements<TYPE>(m_pData, src.m_pData, src.m_nSize); // 元素需要支持 = 运算符 } } InsertAt函数 // 在下标为nIndex的地方,插入nCount个值为newElement的元素。 template<class TYPE, class ARG_TYPE> void CArray<TYPE, ARG_TYPE>::InsertAt(INT_PTR nIndex, ARG_TYPE newElement, INT_PTR nCount /*=1*/) { if(nIndex < 0 || nCount <= 0) AfxThrowInvalidArgException(); // 移动数组元素 if (nIndex >= m_nSize) { // adding after the end of the array SetSize(nIndex + nCount, -1); // grow so nIndex is valid } else { // inserting in the middle of the array INT_PTR nOldSize = m_nSize; SetSize(m_nSize + nCount, -1); // grow it to new size // destroy intial data before copying over it for( int i = 0; i < nCount; i++ ) (m_pData + nOldSize + i)->~TYPE(); // shift old data up to fill gap ::ATL::Checked::memmove_s(m_pData + nIndex + nCount, (nOldSize-nIndex) * sizeof(TYPE), m_pData + nIndex, (nOldSize-nIndex) * sizeof(TYPE)); // re-init slots we copied from memset((void*)(m_pData + nIndex), 0, (size_t)nCount * sizeof(TYPE)); for( int i = 0; i < nCount; i++ ) ::new( (void*)( m_pData + nIndex + i ) ) TYPE; } // insert new value in the gap while (nCount--) m_pData[nIndex++] = newElement; } // 从nStartIndex开始,插入数组pNewArray template<class TYPE, class ARG_TYPE> void CArray<TYPE, ARG_TYPE>::InsertAt(INT_PTR nStartIndex, CArray* pNewArray) { 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)); } } RemoveAt函数 // 移除从下标nIndex开始的nCount个元素 template<class TYPE, class ARG_TYPE> void CArray<TYPE, ARG_TYPE>::RemoveAt(INT_PTR nIndex, INT_PTR nCount) { INT_PTR nUpperBound = nIndex + nCount; if(nIndex < 0 || nCount < 0 || (nUpperBound > m_nSize) || (nUpperBound < nIndex) || (nUpperBound < nCount)) AfxThrowInvalidArgException(); // just remove a range INT_PTR nMoveCount = m_nSize - (nUpperBound); for( int i = 0; i < nCount; i++ ) (m_pData + nIndex + i)->~TYPE(); if (nMoveCount) { ::ATL::Checked::memmove_s(m_pData + nIndex, (size_t)nMoveCount * sizeof(TYPE), m_pData + nUpperBound, (size_t)nMoveCount * sizeof(TYPE)); } m_nSize -= nCount; }