Array,List,Map

Collections類族主要包括三種形式及其不同應用:

 

    Array — CArray, CObArray, CStringArray, CPtrArray, CByteArray, CWordArray, CDWordArray, CTypedPtrArray

 

    List — CList, CObList, CStringList, CPtrList

 

    CMap — CMap, CTypedPtrMap, CMapPtrToPtr, CMapPtrToWord, CMapWordToPtr, CMapStringToPtr

 

整體比較:

 

屬性 類族 特點

內存結構 Array VC源碼CArray::SetSize()中可看到:

TYPE* pNewData = (TYPE*) new BYTE[nNewMax * sizeof(TYPE)];

// copy new data from old

memcpy(pNewData, m_pData, m_nSize * sizeof(TYPE));

// construct remaining elements

ASSERT(nNewSize > m_nSize);

ConstructElements<TYPE>(&pNewData[m_nSize], nNewSize-m_nSize);

// get rid of old stuff (note: no destructors called)

delete[] (BYTE*)m_pData;

m_pData = pNewData;

而在RemoveAt()中則有:

int nMoveCount = m_nSize - (nIndex + nCount);

DestructElements<TYPE>(&m_pData[nIndex], nCount);

if (nMoveCount)

memmove(&m_pData[nIndex], &m_pData[nIndex + nCount],

nMoveCount * sizeof(TYPE));

m_nSize -= nCount;

 

可見Array採用隊列方式存儲數據,因而其內部數據元素是以物理方式順序排列的,所以檢索、順序執行GetAt()等函數的速度是相當快的。但是由於每次隊列長度變化後,數據都要重新申請內存、拷貝內存、釋放內存,因而Insert/Add/RemoveAt()的速度都很慢。

 

如果你使用的數據元素尺寸相當大,而且數組的操作相當複雜,頻繁(1E4以上的)使用InsertAt/SetAt/RemoveAt等,應該考慮使用CList來代替。

 

一個特例是PtrArray/CTypedPtrArray,其內部數據是某個數據地址,而非數據本身,所以其效率更接近CList

 

List VC源碼CList::AddTail()中可看到:

CNode* pNewNode = NewNode(m_pNodeTail, NULL);

pNewNode->data = newElement;

    if (m_pNodeTail != NULL)

m_pNodeTail->pNext = pNewNode;

因而List採用鏈表方式存儲數據,因而當鏈表數據有所變動時,只做了一下指向變動,所以即使數據元素非常多單個數據元素也很大,執行Insert/Add/Remove的速度都很快,但是因爲沒有統一的Index,因而如果要找到某個元素只有遍歷整個鏈表。

 

整體上說,List的使用比較繁瑣,特別爲小尺寸數據設計List更是得不償失的,這也是爲什麼有CWordArray而沒有CWordList的原因,因而在大多數情況下應該有限考慮是否可以使用Array來存儲數據。

 

Map Map採用雜湊(Hashing)表方式來存儲和檢索數據,其內容包括KeyValue的雙列表及其之間的映射關係表。例如在OODBLib用到的::FhtRegister <Class>()函數,在內部使用了Key=Class名稱/Value=Class與數據庫列的映射,從而在使用Class時只需要知道類的名字即可找到與之對應的數據庫映射方法。

在下面的Characteristics表中可看到,Key的數值不可重複,即只能是唯一的(例如在上例中同一個程序中不可能有兩個相同名字的類的聲明),而Value可重複(不同名字的類可有完全相同的變量和函數)

 

儘管雜湊表使用了高效的檢索方式,大量使用CMap::LookUp()函數還是很耗時的,400 000LookUp()執行時間大約是1秒,而同樣次數的CObArray::GetAt()函數只需要0.3秒。

 

應用技巧 Array ①如果在你所使用的場合中,出現下列情況之一:a.數據元素的尺寸很大b.經常需要執行Add函數(例如數據庫在執行Select語句時) 則需要事先執行SetSize(int nSize,int nGrowBy)函數,事先確定大致尺寸(之後仍可增加)及每次增加時一次申請的內存數,從而避免頻繁執行內存申請、複製和刪除工作。

②所有的命名中含Ptr的類都不進行刪除內存的工作,需要自己完成。

③如果在循環中涉及RemoveAt()函數,循環一定要從尾部開始,否則可能漏掉元素,例:

CTypedPtrArray <CObArray,CPeople*> PeopleArray;

for (int i=PeopleArray.GetSize()-1;i>=0;i--)

    {

    if (PeopleArray.GetAt(i)->Name()=="Tom")

        {

        delete PeopleArray.GetAt(i);

        PeopleArray.RemoveAt(i); //cy: 如果從i=0循環,則刪除i後會漏掉對i-1的檢查。

        }

    }

List (暫缺)

Map ①由於LookUp的執行速度比較慢,如果必須進行映射,可在第一此LookUp時將其地址獲得並記錄,此後可直接使用。參考OODBLib/COODBQuery::COODBQuery(),注意

m_cpOODBCDMap=::FhtOODBCDMapOf(aClass.CDMapName());

語句完成了上述操作。

 

 

    下面是MSDNCollections: Choosing a Collection Class章節的一些性能列表及註釋。

 

Collection Shape Features

 

Shape Ordered? Indexed? Insert an element Search for specified element Duplicate elements?

List Yes No Fast Slow Yes

Array Yes By int Slow Slow Yes

Map No By key Fast Fast No (keys)

Yes (values)

 

Characteristics of MFC Collection Classes

Class Uses C++ templates Can be serialized Can be dumped Is type-safe

CArray Yes Yes 1 Yes 1 No

CByteArray No Yes Yes Yes 3

CDWordArray No Yes Yes Yes 3

CList Yes Yes 1 Yes 1 No

CMap Yes Yes 1 Yes 1 No

CMapPtrToPtr No No Yes No

CMapPtrToWord No No Yes No

CMapStringToOb No Yes Yes No

CMapStringToPtr No No Yes No

CMapStringToString No Yes Yes Yes 3

CMapWordToOb No Yes Yes No

CMapWordToPtr No No Yes No

CObArray No Yes Yes No

CObList No Yes Yes No

CPtrArray No No Yes No

CPtrList No No Yes No

CStringArray No Yes Yes Yes 3

CStringList No Yes Yes Yes 3

CTypedPtrArray Yes Depends 2 Yes Yes

CTypedPtrList Yes Depends 2 Yes Yes

CTypedPtrMap Yes Depends 2 Yes Yes

CUIntArray No No Yes Yes 3

CWordArray No Yes Yes Yes 3

 

1. To serialize, you must explicitly call the collection object’s Serialize function; to dump, you must explicitly call its Dump function. You cannot use the form ar << collObj to serialize or the form dmp << collObj to dump.

 

2. Serializability depends on the underlying collection type. For example, if a typed pointer array is based on CObArray, it is serializable; if based on CPtrArray, it is not serializable. In general, the “Ptr” classes cannot be serialized.

 

3. If marked Yes in this column, a nontemplate collection class is type-safe provided you use it as intended. For example, if you store bytes in a CByteArray, the array is type-safe. But if you use it to store characters, its type safety is less certain.

 

發佈了23 篇原創文章 · 獲贊 4 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章