Difference and using: 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来存储数据。

MapMap采用杂凑(Hashing)表方式来存储和检索数据,其内容包括Key和Value的双列表及其之间的映射关系表。例如在OODBLib用到的::FhtRegister <Class>()函数,在内部使用了Key=Class名称/Value=Class与数据库列的映射,从而在使用Class时只需要知道类的名字即可找到与之对应的数据库映射方法。

在下面的Characteristics表中可看到,Key的数值不可重复,即只能是唯一的(例如在上例中同一个程序中不可能有两个相同名字的类的声明),而Value可重复(不同名字的类可有完全相同的变量和函数)。

尽管杂凑表使用了高效的检索方式,大量使用CMap::LookUp()函数还是很耗时的,400 000次LookUp()执行时间大约是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());
语句完成了上述操作。

    下面是MSDN中Collections: Choosing a Collection Class章节的一些性能列表及注释。

Collection Shape Features

ShapeOrdered?Indexed?Insert an elementSearch for specified elementDuplicate elements?
ListYesNoFastSlowYes
ArrayYesBy intSlowSlowYes
MapNoBy keyFastFastNo (keys)
Yes (values)

Characteristics of MFC Collection Classes
ClassUses C++ templatesCan be serializedCan be dumpedIs type-safe
CArrayYesYes 1Yes 1No
CByteArrayNoYesYesYes 3
CDWordArrayNoYesYesYes 3
CListYesYes 1Yes 1No
CMapYesYes 1Yes 1No
CMapPtrToPtrNoNoYesNo
CMapPtrToWordNoNoYesNo
CMapStringToObNoYesYesNo
CMapStringToPtrNoNoYesNo
CMapStringToStringNoYesYesYes 3
CMapWordToObNoYesYesNo
CMapWordToPtrNoNoYesNo
CObArrayNoYesYesNo
CObListNoYesYesNo
CPtrArrayNoNoYesNo
CPtrListNoNoYesNo
CStringArrayNoYesYesYes 3
CStringListNoYesYesYes 3
CTypedPtrArrayYesDepends 2YesYes
CTypedPtrListYesDepends 2YesYes
CTypedPtrMapYesDepends 2YesYes
CUIntArrayNoNoYesYes 3
CWordArrayNoYesYesYes 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.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值