CMap 使用注意说明

CMap应用场景和例子 是 MFC (Microsoft Foundation Classes) 库中的一个模板类,用于实现键值对的映射关系(类似哈希表或字典)。它提供了高效的数据存储和检索功能,适用于需要通过键快速查找值的场景。下面是一个完整的示例,展示如何使用。这行代码声明了一个 MFC 的。上面的示例展示了如何使用。,这样在代码中可以直接使用。定义了这个结构体的别名。 阅读详情

Introduction

Programmers like me, learnt STL::map before CMap always think CMap is difficult to use, and always try to use CMap in the way as a STL::map. In this article, I will explain more information about CMap and what should you do to use it for your own custom class. And as the end of this article, I will show an example of how to use CMap correctly with CString* (note I mean CString pointer and not CString :> )

CMap Internal

The first thing to be noted is that CMap is actually a hash map, and not a tree map (and usually a Red-black tree) as STL::map. Below shows the internal structure of a CMap.

 

How to declare a CMap

Many people get confused about CMap's declaration CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>, why not just CMap<KEY, VALUE>? 

In fact, the ultimate data container in CMap is CPair, and the internal of CPair is {KEY, VALUE}. Therefore, CMap will really store a KEY, and not ARG_KEY. However, if you check with the MFC source code, almost all the internal parameters passing within CMap itself is called with ARG_KEY and ARG_VALUE, therefore, using KEY& as ARG_KEY seems always be a correct answer, except

  1. You are using primitive date types like int, char, where pass-by-value makes no difference (may be even faster) with pass-by-reference
  2. If you use CString as KEY, you should use LPCTSTR as ARG_KEY and not CString&, we will talk more about this later

So what should I do to make CMap works with my ClassX

Well, as I mentioned earlier, CMap is a hash map, a hash map will try to get the "hash value" -- an UINT -- from the key and use that hash value as the index in the hash table (well, actually it is hash value % hash table size). If more then one key have the same hash value, they will be link in a link list. Therefore, the first thing you have to do is to provide a hash function.

CMap will call a templated function HashKey() to do the hashing. The default implementation and specialized version for LPCSTR and LPCWSTR are listed as follows:

// inside <afxtemp.h>template<class ARG_KEY>AFX_INLINE UINT AFXAPI HashKey(ARG_KEY key){	// default identity hash - works for most primitive values	return (DWORD)(((DWORD_PTR)key)>>4);}// inside <strcore.cpp>// specialized implementation for LPCWSTR#if _MSC_VER >= 1100template<> UINT AFXAPI HashKey<LPCWSTR> (LPCWSTR key)#elseUINT AFXAPI HashKey(LPCWSTR key)#endif{	UINT nHash = 0;	while (*key)		nHash = (nHash<<5) + nHash + *key++;	return nHash;}// specialized implementation for LPCSTR#if _MSC_VER >= 1100template<> UINT AFXAPI HashKey<LPCSTR> (LPCSTR key)#elseUINT AFXAPI HashKey(LPCSTR key)#endif{	UINT nHash = 0;	while (*key)		nHash = (nHash<<5) + nHash + *key++;	return nHash;}

As you can see, the default behavior is to "assume" key is a pointer, and convert it to DWORD, and that's why you will get "error C2440: 'type cast': cannot convert from 'ClassXXX' to 'DWORD_PTR'" if you don't provide a specialized HashKey() for your ClassX.

And because MFC only have specialized implementation for the LPCSTR and LPCWSTR, and not for CStringA nor CStringW, this is why if you want to use CString in CMap, you have to declare CMap<CString, LPCTSTR....>

Ok, now you know how CMap calculate the hash value, but since more than one key may have the same hash value, CMap needs to traverse the whole link list to find the one with exactly the same key "content", not only with the same "hash value". And when CMap do the matching, it will call CompareElements(), another templated function.

// inside <afxtemp.h>// noted: when called from CMap, TYPE=KEY, ARG_TYPE=ARG_TYPE// and note pElement1 is TYPE*, not TYPEtemplate<class TYPE, class ARG_TYPE>BOOL AFXAPI CompareElements(const TYPE* pElement1, const ARG_TYPE* pElement2){	ASSERT(AfxIsValidAddress(pElement1, sizeof(TYPE), FALSE));	ASSERT(AfxIsValidAddress(pElement2, sizeof(ARG_TYPE), FALSE));	// for CMap<CString, LPCTSTR...>	// we are comparing CString == LPCTSTR	return *pElement1 == *pElement2;}

Therefore, if you want to use CMap with you own custom ClassX, you will have to provide a specialized implementation for HashKey() and CompareElements().

Example: CMap with CString*

Provided as an example, below is what you need to do to make CMap works with CString*, and of course, using the string content as the key, and not the address of the pointer.

template<> UINT AFXAPI HashKey<CString*> (CString* key){	return (NULL == key) ? 0 : HashKey((LPCTSTR)(*key));}// I don't know why, but CompareElements can't work with CString*// have to define thistypedef CString* LPCString;template<>BOOL AFXAPI CompareElements<LPCString, LPCString> (const LPCString* pElement1, const LPCString* pElement2){	if ( *pElement1 == *pElement2 ) {		// true even if pE1==pE2==NULL		return true;	} else if ( NULL != *pElement1 && NULL != *pElement2 ) {		// both are not NULL		return **pElement1 == **pElement2;	} else {		// either one is NULL		return false;	}}

And the main program is as simple as the following:

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]){	CMap<CString*, CString*, int, int> map;	CString name1 = "Microsoft";	CString name2 = "Microsoft";	map[&name1] = 100;	int x = map[&name2];	printf("%s = %d/n", (LPCTSTR)name1, x);*/	return 0;}--------- console output ---------Microsoft = 100

Please note that the program can compile without error even without the specialized HashKey() and CompareElements(), but of course, the out output will then be 0, probably not what you want.

My final note about CMap

  1. CMap is a hash map and STL::map is a tree map, it is no meaning to compare the two performance (compare apple to orange!). But if you will retrieve the keys in sorted order, then you will have to use STL::map.
  2. The design of HashKey() is critical to the overall performance. You should provide a HashKey() that has low collision rate (different key generally would have different hash value) AND is easy to calculate (not a MD5 of the string, etc..). And we have to note that -- at least for some of the classes -- this is not easy.
  3. When using CMap (as well as STL::hash_map), always beware of the hash table size. As quoted in MSDN "the hash table size should be a prime number. To minimize collisions, the size should be roughly 20 percent larger than the largest anticipated data set". By default, CMap hash table size is 17, which should be ok for around 10 keys. You can change the hash table size with InitHashTable(UINT nHashSize), and only can do so before the first element is added to the map. You can find more prime numbers at here. (And don't mix-up with CMap(UINT nBlockSize), nBlockSize is to acquire more than one CAssoc to speed up the creation of a new node.)

Reference

History

  • 17th March 2006: Initial version uploaded.


Trackback: http://tb.blog.youkuaiyun.com/TrackBack.aspx?PostId=649293

 
MFC中CMap类的用法和原理 CMap 是一个模板类,需要指定键类型、键的参数类型、值类型和值的参数类型。例如:下面展示一些内联代码片。// 键为 int,值为 CString// 哈希表大小为 101。 阅读详情

相关推荐

CMap 集合类使用

一: 功能要求: 需要保存单个的汉字,并且不可重复。 此功能可通过CMap容器完成。 1) 定义 //常用字占两个字节 CMap m_AddCharMap; //偏僻字占四个字节 CMap m_AddPossibleCharMap; 2)设置元素 打开文本,读入常用汉字 CStdioFile

目前打算换一个工作,有招聘windows c++方向的也欢迎联系,北京、济南 最好 3929

RewriteCond: NoCase option for non-regex pattern '-f' is not supported and will be ignored.

报错提示: [Tue Dec 02 13:00:53.567492 2014] [rewrite:warn] [pid 10140:tid 3520] AH00665: RewriteCond: NoCase option for non-regex pattern '-f' is not supported and will be ignored. (/home/xxx/.htaccess

____ 3600

安卓平台下Mali-OpenCL例子

该例子是安卓平台下Mali运行 OpenCL代码,对1080P的彩色图灰度转换。例子说明请看我博客文章。

【Android】MemoryLeakMonitor.jar is not exist! 解决方案

运行环境 使用手机为华为荣耀7A,Android版本为8.0. 部署运行的时候Logcat 报错如下: 2020-05-12 18:04:33.503 4800-4829/****** E/MemoryLeakMonitorManager: MemoryLeakMonitor.jar is not exist! 2020-05-12 18:04:33.505 4800-4800/****** E/Minikin: Could not get cmap table size! 大致意思是没找到Memo.

hnzkxlw的专栏 8677

Win11大版本更新失败:系统保留分区空间不足的终极解决方案

本文针对Windows 11大版本更新时遇到的“系统保留分区空间不足”错误,提供了详细的诊断与解决方案。核心问题在于EFI系统分区(ESP)空间过小,导致更新失败。文章重点介绍了使用傲梅分区助手等第三方工具安全扩展EFI分区的完整步骤,并提供了手动清理、使用安装介质修复等替代方案,帮助用户彻底解决更新障碍,顺利完成Win11升级。

weixin_29280219的博客 948

Mac上快速部署DeepSeek模型:Ollama终端操作全指南

本文详细介绍了在Mac上使用Ollama终端快速部署DeepSeek模型的完整指南。从硬件要求、Ollama安装、模型下载运行,到高级配置、可视化界面及常见问题解决,提供了全流程操作步骤与优化技巧,帮助开发者高效搭建本地AI助手,实现稳定、私密的离线使用体验。

weixin_29251567的博客 550

Android 华为手机上点击闪退

在华为8.0上出现点击按钮闪退的情况,报了这样的日志:Minikin: Could not get cmap table size!     MemoryLeakMonitorManager: MemoryLeakMonitor.jar is not exist! 最后解决:去掉某个Activity里的android:screenOrientation="portrait", Android ...

qin的博客 8397

Python逆向爬取Tik Tok,MsToken,X-Bogus以及signature

tiktok作为字节海外的自媒体平台,具有很非常大的价值,本文旨在教会大家实现Tik Tok的签名获取以及数据的最终爬取。

weixin_74305707的博客 3268

matplotlib.pyplot——cmap直观理解

最近在看《深入浅出Python机器学习》,敲案例时发现matplotlib里cmap参数的使用方法发生了一些变化,索性整理了一下cmap相关的内容,这里是cmap预设值的官方图例,文中也会放出。文中表达如有不正确的地方,欢迎指出~ WHAT 关于cmap的个人理解 cmap参数接受一个值(每个值代表一种配色方案),并将该值对应的颜色图分配给当前图窗。 形象化:如果将当前图窗比作一幅简笔画,则cm...

Lilies is here. 12万+

hcaptcha无感验证码逆向实战:从接口分析到环境补全

本文详细解析了hcaptcha无感验证码的逆向实战过程。通过分析核心接口与加密逻辑,重点介绍了采用环境补全策略来模拟真实浏览器环境,从而绕过验证码检测。文章提供了从接口抓包、剖析hsw.js加密核心到使用Node.js搭建模拟环境的完整步骤,为自动化操作提供了一种稳健的解决方案。

weixin_29324401的博客 1151

VMware 安装 Windows11

一、下载win11的镜像文件 可以在MSDN网站下载: MSDN系统库-致力于原版windows生态服务 二、创建虚拟机 1.双击打开VMware虚拟机,点击创建新的虚拟机 2.选择典型(推荐),然后点击下一步 3.在安装程序光盘映像文件下,点击浏览按钮,选择Windows 11ISO镜像文件所在的路径,在Windows 11安装文件路径中不要有中文或其他特殊符号,否则有可能引起错误。然后点击下一步 4.在选择客户机操作系统界...

m0_56015193的博客 7016

训练yolov5时候报错ValueError: Format ‘jpg‘ is not supported (supported formats: eps, pdf, pgf,

ValueError: Format 'jpg' is not supported (supported formats: eps, pdf, pgf, png, ps, raw, rgba, svg, svgz)报错

qq_42309888的博客 1679

ollama环境变量配置:修改ollama的数据路径(安装路径)

ollama安装模型,如果很大,会占用C盘空间,影响系统运行速度,通过设置环境变量,来改变ollama放目录的地址。

正经教主是个热衷于正经学习分享的教主。 1万+

CMap 使用注意说明(English)

 IntroductionProgrammers like me, learnt STL::map before CMap always think CMap is difficult to use, and always try to use CMap in the way as a STL::map. In this article, I will explain more infor

magictong的专栏 3075

YOLO11训练中的批量大小(Batch Size)选择策略:分析Batch Size对训练速度、显存占用和模型性能的影响

在深度学习训练过程中,Batch Size(批量大小)是一个至关重要的超参数,它指的是单次迭代中用于更新模型权重的样本数量。简单来说,当我们训练神经网络时,不会一次性将所有数据喂给模型,而是将数据分成若干个小批次(batch),每个批次包含一定数量的样本,这个数量就是Batch Size。 Batch Size的核心作用在于平衡训练效率与模型性能。较小的Batch Size意味着每次更新权重时参考的信息较少,可能导致训练过程更加随机,但有时能带来更好的泛化能力;较大的Batch Size则能提供更稳定的梯

本博客聚焦 YOLOv11 全流程落地,涵盖架构优化、数据集处理、训练技巧与多场景部署,兼及国产数据库、Java 开发与 AI 模型应用,内容兼顾理论与工程实践,为开发者提供系统干货,助力高效提升技术能力。 323

ARM6818嵌入式视频播放器:硬解加速与Framebuffer渲染实战

嵌入式Linux音视频系统是智能座舱、工业HMI等场景的核心能力,其本质是软硬协同的实时多媒体处理系统。原理上需打通内核驱动(如VPU硬件编解码、FIMD多图层合成)、用户空间框架(GStreamer pipeline定制、SDL2硬件渲染)与应用层同步机制(PTS/HTS双时钟校准)。技术价值在于显著降低CPU负载(硬解可压至15%以下)、提升启动速度(<1.2s首帧)并保障音画同步精度(±3ms级)。典型应用场景包括车载信息娱乐、边缘AI终端及无X11的工控显示设备。本文基于ARM6818平台,深入VP

weixin_32456485的博客 77

【免费下载】 PDFJS使用的CMap字体文件

PDFJS使用的CMap字体文件 【下载地址】PDFJS使用的CMap字体文件 本仓库提供了一个资源文件,专门用于PDFJS的CMap字体文件。该文件适用于前端开发场景,特别是当PDF文件使用了PDFJS不支持的字体文件时,需要额外为PDFJS提供相应的字体文件 ...

gitblog_09744的博客 709

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

cmap参数 plt_plt.imshow的参数有哪些?

plt.imshow(X,cmap=None,norm=None,aspect=None,interpolation=None,alpha=None,vmin=None,vmax=None,origin=None,extent=None,shape=None,filternorm=1,filterrad=4.0,imlim=None,resample=None,url=None,*,data=No...

weixin_39667626的博客 3580

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

【python】matplotlib(rose)

在 matplotlib 中使用 ax.plot_surface 之前,你需要确保已经创建了一个三维的坐标轴对象 ax。是一个在三维空间中绘制表面的函数,通常用于 matplotlib 库中的 Axes3D 对象。这个函数可以用来创建三维图形,其中表面由给定的 X、Y、Z 数据点集合定义。使用不同的颜色映射(cmap)可以极大地改变图形的视觉效果,因此选择合适的颜色映射是很重要的。plot_surface 绘制的表面是封闭的,即它会根据数据点自动连接边缘以形成完整的表面。绿色去掉,保留玫瑰花的红。

bryant_meng 953

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

CMap

英文原文:http://www.codeproject.com/KB/architecture/cmap_howto.aspx?print=true 来自:http://blog.youkuaiyun.com/ggggqqqqihc/archive/2008/01/11/2037666.aspx 简介 一些像我一样的程序员,先学STL::map再学CMap,常常认为CMap很难用,而且总是使用S

云里雾里的专栏 2033

VC的CMap类和STL的map的使用及使用过程中遇到的错误

<br />VC的CMap类和STL的map的使用及使用过程中遇到的错误 <br /><br />1、CMap类:<br />映射表类(CMap)是MFC集合类中的一个模板类,它是对Hash表的一种实现,也称作为“字典”,就像一种只有两列的表格,一列是关键字,一列是数据项,它们是一一对应的,。<br />关键字是唯一的,给出一个关键字,映射表类会很快找到对应的数据项。映射表的查找是以哈希表的方式进行的,因此在映射表中查找数值项的速度很快。映射类最适用于需要根据关键字进行快速检索的场合,他这个有点像数组,比如

luxiaoyu_sdc的专栏 5187

【亲测免费】 cmap-resources 使用指南

--- ## 项目介绍 **cmap-resources** 是由 Adobe Type Tools 提供的一个开源项目,专注于提供 cmap 表相关的资源和工具。CMap 文件在字体技术中扮演重要角色,用于将 Unicode 字符映射到字体内部编码,这对于跨平台的文字处理至关重要。这个仓库集合了多种语言和编码方案的 CMap 数据,对于开发人员和字体设计师来说,是理解和操作字符编码映射不可或...

gitblog_00171的博客 936

CMap常用函数

CMap是MFC中基于哈希表的键值对容器类,支持高效插入(SetAt)、查找(Lookup)、删除(RemoveKey)和遍历(GetNextAssoc)操作。使用时需声明键值类型,键必须唯一,插入重复键会覆盖原值。典型应用包括配置表、缓存数据等需要快速查询的场景,但需注意其无序性特点。CMap自动管理内存,提供O(1)平均时间复杂度的操作效率。

qq_23314263的博客 775

cmap用法,很详细(转)

一、 Map的基本知识  MFC中的提供了基于模板的CMap类。利用CMap模板类,可以处理特定的数据类型,例如用户自定义的类或结构体等。同时,MFC也提供了基于指定 数据类型的非模板类,其中包括: 类名 关键字类型 元素值类型 CMapWordToPtr WORDS Void pointers CMapPtrToWord Void pointers WORDS CMapPtrToPtr Void pointers Void pointe..

3124

CMap详解

CMap详解 (第一部分) 如何声明CMap 许多人对Cmap的声明模式CMap感到迷惑,为什么不用CMap呢? 实际上,CMap中的的数据最终会是CPair,而CPair内部是(KEY,VALUE)。因此,CMap其实存储的是KEY,而非ARG_KEY。然而,如果你查看MFC的源代码,几乎CMap所有的内部参数传递都是访问ARG_KEY和ARG_VALUE,因此,使用KEY&来代替ARG

TXH0001的专栏 1万+
上一篇: VMware Tools 5.5.2 with Fedora Core 6
下一篇: 对posix线程机制的c++封装实现
suppercom
博客等级 码龄22年 4粉丝 3原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值