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如何使用,用法举例》中,已经非常详细的说明了CMap参数的用法,也在其他的专题中介绍过了其它模板类的实化过程,不过我还是担心是否每个人都有足够的耐心去看完那些蜿蜒之天际的文章。所以,我们把CArray、CList以及CMap的参数问题独立出来,在此着重的讲解一番。

还是先看一个简单的实化例子吧:

typdedef CMap<CString, LPCTSTR,CString, CString&>   CStrMap;

显然,向这样的用法,是无可厚非的,就像我们国家的中医,在经过无数次致命的尝试之后,得到了这个不再苦涩的,似乎也可以包治百病的灵丹妙药。可是,这毕竟是个令人心惊胆战的用法,尤其对于那些并不熟悉并试图熟悉CMap的小家伙们。我们还是先来看看CMap类型参数列表吧:

template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>

它继承了CArray以及CList的参数风格,将传入类型与返回类型分开,其中带有ARG_前缀的是传入类型,另外一个则是返回类型,这已经是我们不止一次的抱怨为什么要将类型参数分开了,其实实践证明,它们的确可以被合并起来,不过参数传入的灵活性将会受到部分的影响。

我们在《CMap如何使用,用法举例》中,已经比较详细的讨论过为什么CMap的ARG_KEY与KEY可以是不同的参数类型,其实这可以推广到所有类似的模板之中。不得不声明的一点是:在CMap中,实际存储的是KEY以及VALUE。那么,现在我们来看看CStrMap到底是如何实化的。

我们看到在CMap中,类型参数ARG_KEY的引参是LPCTSTR,而与之对应的KEY的引参却又是CString,它们是如此的固执,既然都指代了同样的内容,为什么又偏偏将对方视若不见呢?其实,这与CMap的内部实现存在着密不可分的关系,由于在CMap的内部,建立了一个Hash表,所以,必须将所有的传入参数置换为类似于int类型的整数,这样才可以符合散列函数的参数类型,否则CMap在编译时会报错。那么又是为什么?我们可以将ARG_KEY使用LPCTSTR来实化呢?其实,这又牵扯到了Hash表的实现问题,当然其中也包含了CString的实现问题。我们知道,存储在CStrMap内部的KEY仍然是CString,而我们对Hash表的操作,无非也就是给出一个整型的数,然后根据散列函数来寻找一个存储地址而已,尤其,当我们使用operator[]操作符的时候,如果我们给定的KEY所对应的VALUE并不存在的话,CMap会自动的为我们生成一个相应的元组,而如果你继而对它赋值的话,它会将ARG_KEY直接赋值给KEY,而这里就涉及到KEY的赋值构造函数了(其实,我更想叫它赋值操作符),现在我们使用的KEY是CString,而我们却要将一个LPCTSTR赋值于它,所以,我们就必须重载这个函数,其实也就是这样的一个函数:

CString& operator=(LPCTSTR lpsz);

显然,这立即解决了我们的问题,不过,这仅仅是从逻辑功能层面,如果你传入的KEY是个很长的字符串的话,那么必然会对CStrMap的性能造成影响,其实这样的隐患也同样存在于VALUE身上,乃至其它类似的模板类上,这不得不引起我们的足够重视!

C++,这门完美的近乎没有任何瑕疵的OOP语言,无疑就是闪耀星空的旷世巨献,然而,这似乎并没有引起每个人的共鸣。C++从C中的诞生,似乎就注定了,它永远都不可能像JAVA那样血统纯正,我不得不承认,它并非一个严格意义上的OOP(Oriented-object language,面向对象设计语言),然而就是这种近乎不合理的缺陷,却又造就了它近乎不合理的适应性,我是向来瞧不起解释性语言的,因为我本人就编写过脚本的解释器,实践证明,它们的效率要远远的落后于编译性语言,虽然它们常常号称自己如何的平台无关,如何的小而强大。

但,对于绝大多数的程序员来说,JAVA的确有很多的优势,也许其中之一,便是简单易学,其实这似乎更像一个借口。指针一度是困扰相当一部分程序员的暗物质,而C++更将这种震慑发挥到极致。显然C++的确很难,难到令这个世界上,至少50%以上的程序员,望而却步。然而一个几乎包罗万象的程序设计语言,几乎能容忍一切的全能语言,它到底有着什么样的魔力,却令另外50%的人如此的钟意,如此的着迷?

偏题三千里,言归正传。

至于C++的性能,似乎一直被OOP的性格所掩盖,而OOP主张的面向对象编程,更让许多窃窃私语的程序员有了足够的底气发言,同时他们宣称,C++显然就是应该由对象统治的世界,其实--大错特错,简直错的一败涂地。C++,归根结底,还是由指针执政,以致我们可以直接的操纵内存,直接和系统底层会话,并且还能实现我们空前强大的令人炫目的多态。所以,我们必须要利用这个得天独厚的资源。

偏题一千里,再言归正传。

现在,我已经知道,直接在C++程序中使用对象,是何等的不专业,显然,我们更应该使用指针,曾经有一位高人,不无自我解嘲的说,他写程序的第一年连一个指针都不敢用,后来又在他的婴幼儿奶粉级的大作中大肆声讨指针,可想他曾经遭受了指针怎样的折磨。

在程序中使用指针,几乎可以使你的程序恢复到C的性能级别,显然我不会回避你正在思考命题,不错,C的性能的确要高于C++,而汇编语言的性能显然要进一步的高于C,只要学过一点编译原理的人,应该不会反对这个早已过时的辩论焦点。关键在于,从C过度到C++,已经是一种编程思维的转变。然而很多人,既没有继承C的高性能性,又未能领悟C++的封装、继承与多态性,却妄图从C直接飞到C++上,却被挂在了C与C++的中间,左右为难,大概停留到了C+这门语言去了。

言归正传。

我们在定义函数的时候,应该尽可能的少传对象,而更应该传指针或者引用,我们知道对于编译器内部来说,引用其实就是一个指针。这最主要的原因是,我们不必再为函数参数的圧栈而苦恼不已;同样,我们也不应该在函数结束之后,用对象来返回,这同样增加了函数圧栈的开销,而更应该适可的返回一个指针或者一个引用,当然,这样的指针和引用,绝对不能指向一个函数体内的临时对象。然而传入CMap中的类型参数,到底应该是什么,这似乎已经上升到了算法的层次,从而使我们对于实化本身的讨论变的毫无意义。

我也许会主张,将CMap实化成这种模样:

typedef CMap<CString*, CString*, CString*, CString*>    CStrPtrMap;

个中缘由,当然还是出于对效率的考虑,我们在SetAt之前先new出一个CString对象,然后将其填入CStrPtrMap,这样的好处在于我们在SetAt的时候不需要去调用CString的赋值构造函数,而仅仅作简单的数据拷贝,这样的行为几乎适合所有的复杂数据结构,包括类,结构体。当然,唯一不能忘记的是,必须在必要的时候释放那些new出来的CString对象,否则,将会导致严重的内存泄露!

当然,你可以根据自己的兴趣,去总结到底应该选择怎么样的KEY与ARG_KEY。由于一般来说,KEY都不可能是太大的字符串,从而为了兼顾效果与效率,作为一种折中的方案就是定义这样的一个类似于字典的CMap实化类:

typedef CMap<CString, LPCTSTR, CString*, CString*>    CStrPtrMap;

啊,这又是一个长着人身猪脸的八戒啊!不过,既然要去西天取经,八戒就八戒吧。

当然,千叮万嘱的还是,别忘记释放为CString*申请的内存!至于另外两个模板的参数选择,基本上大同小异,并且要比CMap简单,就不再罗嗦了。

CArray,CList,CMap如何实例化的更多相关文章

  1. CArray CList CMap 插入与遍历效率对比

    前言:程序中经常用到不定量数组,选择上可以使用CArray,CList,CMap,而这三者插入及遍历的效率,未测试过,随着数据量越来越大,需要做程序上的优化,于是比较下三种类型的插入盒遍历的效率. 一 ...

  2. MFC笔记

    一.Win32基本程序概念 所有的windows程序都必须载入windows.h MFC程序都有一个Stdafx.h文件,它载入了MFC框架必须的文件. Windows程序以消息为基础,以事件驱动之. ...

  3. MFC容器类介绍

    我们知道如果是单个的少数几个值弄些int , long,float ,double等类型的变量来装这些值就行了.但如果值太多这样就比较麻烦.当然数据超级多时就直接放数据库里存着去了. 但如果数值不多不 ...

  4. MFC类的结构

    1. CObject类,MFC库中绝大部分类的基类,封装了MFC中的最基本机制. 运行时类信息机制/动态创建机制/序列化机制等... 2. CCmdtarget - 消息映射机制最基类 3. CWin ...

  5. C++MFC编程笔记day01 MFC介绍、创建MFC程序和重写消息处理

    一.MFC概念和作用 1.全称Microsoft Foundation Class Library,我们称为微软基础类库,封闭了绝大部分的win32 Api函数,C++语法中的数据结构,程序的运行流程 ...

  6. SpringMVC之参数绑定

    1.Controller package com.tz.controller; import org.springframework.beans.factory.annotation.Required ...

  7. [MFC] CList

    1.CList说明 类CList支持可按顺序或按值访问的非唯一对象的有序列表.CList 列表与双链接列表行为相似. template < class TYPE, class ARG_TYPE ...

  8. MFC中CArray类原理及其应用

    1.CArray类应用 函数简介CArray::GetSize int GetSize( ) const;取得当前数组元素个数. CArray::GetUpperBound int GetUpperB ...

  9. Spring中Bean的实例化

                                    Spring中Bean的实例化 在介绍Bean的三种实例化的方式之前,我们首先需要介绍一下什么是Bean,以及Bean的配置方式. 如果 ...

随机推荐

  1. 利用expect和sshpass完美非交互性执行远端命令

    yum install expect -y expect 参考:http://blog.csdn.net/snow_114/article/details/53245466 yum install s ...

  2. grunt-init 默认模板目录更正

    grunt-init是依赖grunt项目管理的脚手架工具,各种优点无须赘述,默认的template路径的作用:可以把自定义或其他模板放置其中,应用的时候直接调用模板名,不用每次寻找路径: 在安装gru ...

  3. log4cpp之Category

    body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...

  4. VirtualBox安装Redhat9.0

    1.准备软件 虚拟机:VirtualBox-4.3.8-92456-Win.exe RedHat:shrike-i386-disc1.iso     shrike-i386-disc2.iso     ...

  5. APUE学习笔记——3.文件共享与fcntl介绍

    基本概念 内核使用3个数据结构描述一个打开的文件:进程表.文件表.V节点表 首先了解3种数据结构的概念     1 进程表         每一个进程有一个进程表.进程表里是一组打开的文件描述符,如标 ...

  6. SpreadJS 在 Angular2 中支持绑定哪些属性?

    SpreadJS 纯前端表格控件是基于 HTML5 的 JavaScript 电子表格和网格功能控件,提供了完备的公式引擎.排序.过滤.输入控件.数据可视化.Excel 导入/导出等功能,适用于 .N ...

  7. Python matplotlib 数据分布

    利用plt.hist() import matplotlib.pylab as plt %matplotlib inline plt.figure(figsize=(21, 12)) plt.hist ...

  8. [interview]螺旋队列问题

    摘要 本文主要讲解三种螺旋队列的实现方式和打印输出: 从中心往外端顺时针旋转,记为『外螺旋队列』 从左顶点开始,绕剩下的最大圈顺时针往内旋转,记为『内螺旋队列』 从左顶点开始,之字形旋转(只能同行同列 ...

  9. Form元素与字体

    前言 以前写代码的时候总是喜欢在body元素中写字体属性,用以控制全局字体样式,后来发现表单元素中的字体样式并不能被控制,郁闷的不行. 解决方法 因为表单元素无法继承body的字体属性,所以要单独设置 ...

  10. appium-java,切换源生app和webview

    方法 public void swith_app(AndroidDriver AndroidDriver){ //切换到源生app System.out.println(AndroidDriver.g ...