//指针类型成员的汇编代码 for (; nCount--; pElements++) 004354D0 EB 09 jmp ConstructElements+6Bh (004354db) 004354D2 8B 55 08 mov edx,dword ptr [ebp+8] 004354D5 83 C2 04 add edx,4 004354D8 89 55 08 mov dword ptr [ebp+8],edx 004354DB 8B 45 0C mov eax,dword ptr [ebp+0Ch] 004354DE 8B 4D 0C mov ecx,dword ptr [ebp+0Ch] 004354E1 83 E9 01 sub ecx,1 004354E4 89 4D 0C mov dword ptr [ebp+0Ch],ecx 004354E7 85 C0 test eax,eax 004354E9 74 13 je ConstructElements+8Eh (004354fe) 62: ::new((void*)pElements) TYPE; 004354EB 8B 55 08 mov edx,dword ptr [ebp+8] 004354EE 52 push edx 004354EF 6A 04 push 4 004354F1 E8 AB AF FD FF call @ILT+62620(operator new) (004104a1) 004354F6 83 C4 08 add esp,8 004354F9 89 45 FC mov dword ptr [ebp-4],eax 004354FC EB D4 jmp ConstructElements+62h (004354d2) 0x052046b8 //对象类型的汇编代码 61: for (; nCount--; pElements++) //nCount非0为真,否则假 终止循环 ;) 00436415 EB 09 jmp ConstructElements+80h (00436420) 00436417 8B 55 08 mov edx,dword ptr [ebp+8] 0043641A 83 C2 14 add edx,14h 0043641D 89 55 08 mov dword ptr [ebp+8],edx 00436420 8B 45 0C mov eax,dword ptr [ebp+0Ch] 00436423 8B 4D 0C mov ecx,dword ptr [ebp+0Ch] 00436426 83 E9 01 sub ecx,1 00436429 89 4D 0C mov dword ptr [ebp+0Ch],ecx 0043642C 85 C0 test eax,eax 0043642E 74 41 je ConstructElements+0D1h (00436471) 62: ::new((void*)pElements) TYPE; 00436430 8B 55 08 mov edx,dword ptr [ebp+8] 00436433 52 push edx 00436434 6A 14 push 14h 00436436 E8 66 A0 FD FF call @ILT+62620(operator new) (004104a1) 0043643B 83 C4 08 add esp,8 0043643E 89 45 EC mov dword ptr [ebp-14h],eax 00436441 C7 45 FC 00 00 00 00 mov dword ptr [ebp-4],0 00436448 83 7D EC 00 cmp dword ptr [ebp-14h],0 0043644C 74 0D je ConstructElements+0BBh (0043645b) 0043644E 8B 4D EC mov ecx,dword ptr [ebp-14h] 00436451 E8 D5 74 FE FF call @ILT+117030(_JM_Identity_Sub::_JM_Identity_Sub) (0041d92b) //调用对象构造函数 00436456 89 45 E8 mov dword ptr [ebp-18h],eax 00436459 EB 07 jmp ConstructElements+0C2h (00436462) 0043645B C7 45 E8 00 00 00 00 mov dword ptr [ebp-18h],0 00436462 8B 45 E8 mov eax,dword ptr [ebp-18h] 00436465 89 45 F0 mov dword ptr [ebp-10h],eax 00436468 C7 45 FC FF FF FF FF mov dword ptr [ebp-4],0FFFFFFFFh 0043646F EB A6 jmp ConstructElements+77h (00436417) 63: } 00436471 8B 4D F4 mov ecx,dword ptr [ebp-0Ch] 00436474 64 89 0D 00 00 00 00 mov dword ptr fs:[0],ecx 0043647B 5F pop edi 0043647C 5E pop esi 0043647D 5B pop ebx 0043647E 83 C4 58 add esp,58h 00436481 3B EC cmp ebp,esp 00436483 E8 08 BE 93 00 call CSaleAdvanceWriteOffListForm::InitListHeader+278h (0093be08) 00436488 8B E5 mov esp,ebp 0043648A 5D pop ebp 0043648B C2 08 00 ret 8
template<class TYPE> AFX_INLINE void AFXAPI ConstructElements(TYPE* pElements, int nCount) { ASSERT(nCount == 0 || AfxIsValidAddress(pElements, nCount * sizeof(TYPE))); // first do bit-wise zero initialization memset((void*)pElements, 0, nCount * sizeof(TYPE)); // then call the constructor(s) for (; nCount--; pElements++) ::new((void*)pElements) TYPE; } template<class TYPE> AFX_INLINE void AFXAPI DestructElements(TYPE* pElements, int nCount) { ASSERT(nCount == 0 || AfxIsValidAddress(pElements, nCount * sizeof(TYPE))); // call the destructor(s) for (; nCount--; pElements++) pElements->~TYPE(); }
最近在mfc中用到字典,自己不会在网上查了资料。简单总结一下:
一,CMap是什么?
映射(Map),又称为字典(Dictionary),是由关键字(Key)及其对应的元素值(Value)所组成的元素单
元(Element)的表单式集合。CMap是一个mfc的模板类,可以建立一个从任意类型的变量到另外一个任意类型的
变量的映射(map),用的是哈希表作存储,因此速度较快。对于要求查找速度快一般用数组,对于增加/删除操作
方便的都用链表,但要是两者综合一下,最好还是用合希表。
二,要注意的几个地方:
1.如何声明CMap
许多人对Cmap的声明模式CMap<KEY,ARG_KEY,VALUE,ARG_VALUE>感到迷惑,为什么不用CMap<KEY,VALUE>
呢?实际上,CMap中的的数据最终会是CPair,而CPair内部是(KEY,VALUE)。因此,CMap其实存储的是KEY
,而非ARG_KEY。然而,如果你查看MFC的源代码,几乎CMap所有的内部参数传递都是访问ARG_KEY和ARG_VALUE,因此,使用KEY&来代替ARG_KEY似乎是正确的,除了在这些情况下:
1 应用简单的数据类型,如int ,char用值传递与参数传递没有什么不同
2 如果用CString作为KEY,你应该用LPCTSTR做ARG_KEY而非CString&。
2.有哪些与Map相关的典型操:
1 向Map中插入具有给定关键字的元素单元。
2 在Map中查找具有给定关键字的元素单元。
3 在Map中删除具有给定关键字的元素单元。
4 枚举(遍历)Map中的所有元素单元。
三,简单的例子:
例子一: 我们来看一个CMap的用法,下面示例代码:
CMap<int,int&,CPoint,CPoint&> myMap;
//初始化哈希表,并指定其大小(取奇数)。MyMap.InitHashTable(257);
//向myMap中添加元素单元。
for (int i=0;i < 200;i++)
myMap.SetAt( i, CPoint(i, i) );
// 删除实际值为偶数的关键字所对应的的元素单元。
POSITION pos = myMap.GetStartPosition();
int nKey;
CPoint pt;
while (pos != NULL)
{
myMap.GetNextAssoc( pos, nKey, pt );
if ((nKey%2) == 0)
myMap.RemoveKey( nKey );
}
#ifdef _DEBUG
afxDump.SetDepth( 1 );
afxDump << "myMap: " << &myMap << "/n";CMap<int,int&,CPoint,CPoint&> myMap;
//初始化哈希表,并指定其大小(取奇数)。MyMap.InitHashTable(257);
//向myMap中添加元素单元。
for (int i=0;i < 200;i++)
myMap.SetAt( i, CPoint(i, i) );
// 删除实际值为偶数的关键字所对应的的元素单元。
POSITION pos = myMap.GetStartPosition();
int nKey;
CPoint pt;
while (pos != NULL)
{
myMap.GetNextAssoc( pos, nKey, pt );
if ((nKey%2) == 0)
myMap.RemoveKey( nKey );
}
#ifdef _DEBUG
afxDump.SetDepth( 1 );
afxDump << "myMap: " << &myMap << "/n";
CMap是个很不错的数据结构,尤其在你建立一个字典的时候。比如idcountry的含义是"中国",这就是一个元组
,也就是一个Pair,Key是"idcountry",而Value是"中国"。
例子二:
1、定义一个CMAP,向这个CMAP中增加数据项(键-值对)。
CMap<CString, LPCTSTR, CString, LPCTSTR>m_ItemMap;
CString strKey = _T(""), str = _T("");
int i;
for(i = 0; i < 5; i++)
{
strKey.Format("%d", i); //这个是键
str.Format("A%d", i); //键对应的值
m_ItemMap.SetAt(strKey, str);
}
2、遍历正个CMAP的常用方法。
POSITION pos = m_ItemMap.GetStartPosition();
while(pos)
{
m_ItemMap.GetNextAssoc(pos, strKey, str);
cout<< strKey<< ":"<< str<< endl;
}
3、在CMAP中查找相应的数据项。
CString pReset;
if(m_ItemMap.Lookup("1", pReset))
{
cout<<pReset<<endl;
}
cmap用法,很详细(转)
一、 Map的基本知识
MFC中的提供了基于模板的CMap类。利用CMap模板类,可以处理特定的数据类型,例如用户自定义的类或结构体等。同时,MFC也提供了基于指定 数据类型的非模板类,其中包括:
类名 | 关键字类型 | 元素值类型 |
CMapWordToPtr | WORDS | Void pointers |
CMapPtrToWord | Void | pointers WORDS |
CMapPtrToPtr | Void pointers | Void pointers |
CMapWordToOb | WORDS | Objects |
CMapStringToOb | Strings | Objects |
CMapStringToPtr | Strings | Void pointers |
CMapStringToString | Strings | String |
二、 Map的工作原理
在MFC的CMap及其相关的Map类中,只要对Map进行正确设置,Lookup函数通常能够一次到位的查找到任意元素,而很少需要进行两次或者三 次以上的查找比对。
struct CAssoc { CAssoc* pNext; UINT nHashValue; CString key; CString value; }; |
nHashTableSize是哈希表中元素的数目(默认情况下,哈希表的大 小为17)。
如果在哈希表中的索引值为i的位置已经容纳了一个CAssoc指针,那么MFC将建立一个单独的CAssoc结构体的链表(List),链表中的第一 个CAssoc结构体的地址被存储到哈希表中,而将第二个CAssoc结构体的地址存储到前一个CAssoc结构体的pNext域,以此类推。
但是,正如我们先前所讨论的那样,只要正确设置Map,链表中的元素一般就不会超过三个,这就意味着,查找通常可 以在三次元素比对操作之内完成。
三、 优化查找效率
微软推荐将哈希表的大小设置为Map中所存储元素数目的 110% ~120%,以使得Map的应用性能在内存消耗和查找效率之间取得相对平衡。
在MFC中,指定哈希表大小,可调用InitHashTable()函数:
map.InitHashTable(1200);
从统计学上考虑,用奇数作为哈希表的大小也将有助于减少冲突的发生。因此,初始化一个存储1000个元素的哈希表的InitHashTable() 函数可以如下形式使用:
map.InitHashTable(1201);
同时,在InitHashTable()函数的调用时机上,应该注意的是,该函数应当在map包含有任何元素之前使。如果map中已经包含了一个或者 更多的元素,那么,重新改变map的大小,将会引发断言(Assertion)错误。
尽管MFC中所使用的哈希算法能够适应于大多数场合,但如果您真的有所需要,或者,只要你愿意,用户也可以使用自己的算法来取代原有的算法。对于一个 输入的关键字的值,要计算出它的哈希值,MFC通常调用一个全局模板函数HashKey(),对于大多数数据类型而言,HashKey()函数是以下面的 方式实现的:
AFX_INLINE UINT AFXAPI HashKey(ARG_KEY key) { //一般情况的默认算法。 return ((UINT)(void*)(DWORD)key) >> 4; } 但对于字符串而言,其具体的实现方式如下: UINT AFXAPI HashKey(LPCWSTR key) // Unicode 编码字符串 { UINT nHash = 0; while (*key) nHash = (nHash<<5) + nHash + *key++; return nHash; } UINT AFXAPI HashKey(LPCSTR key) // ANSI编码字符串 { UINT nHash = 0; while (*key) nHash = (nHash<<5) + nHash + *key++; return nHash; } |
要实现对应于特定数据类型的用户自定义哈希算法,您可以使用上述的字符串版本的HashKey()函数作为参考,写一个类似的特定类型的 HashKey()函数。
四、 使用MFC中的CMap类
构造函数:
CMap | 构造一个关键字和元素值映射的集合类。 |
操作:
Lookup | 通过给定的关键字查找相应的元素值。 |
SetAt | 向Map中插入一个元素单元;若存在匹配键字,则替代之。 |
operator [] | 向Map中插入一个元素 -SetAt的子操作 |
RemoveKey | 移除由关键字标示的元素单元 |
RemoveAll | 移除Map中的所有元素单元 |
GetStartPosition | 返回第一个元素单元的位置 |
GetNextAssoc | 读取下一个元素单元 |
GetHashTableSize | 返回哈希表的大小(元素单元的数目) |
InitHashTable | 初始化哈希表,并指定它的大小 |
状态:
GetCount | 返回Map中元素的数目 |
IsEmpty | 检查Map是否为空(无元素单元) |
应用实例如下:
MyMap.InitHashTable(257); |
2、选择适当大小的奇数-- 或者,有可能的话,使用素数的效果会更好一些--来作为哈希表的初始值。
3、然后,向myMap中添加元素单元。
4、使用myMap进行数据映射、查找、遍历等操作。
5、调用myMap.RemoveAll()函数移除所有元素,释放myMap占用的内存空间。
CMap对应IMPLEMENT_SERIAL,从而支持用户对其元素进行串行化(Serialization)以及倾注(Dumping)操作。在 对CMap的独立元素进行倾注操作时,应该注意的是,你必须将倾注环境(Dump Context)的深度设置为1或者更大的数字。
- 外文名
- CArray
- 属 性
- 计算机科学领域术语
VC中的CArray的使用
关于 CArray类
2007年01月10日 星期三 17:18
|
南来地,北往的,上班的,下岗的,走过路过不要错过!
======================个性签名=====================
之前认为Apple 的iOS 设计的要比 Android 稳定,我错了吗?
下载的许多客户端程序/游戏程序,经常会Crash,是程序写的不好(内存泄漏?刚启动也会吗?)还是iOS本身的不稳定!!!
如果在Android手机中可以简单联接到ddms,就可以查看系统log,很容易看到程序为什么出错,在iPhone中如何得知呢?试试Organizer吧,分析一下Device logs,也许有用.