




全文预览已结束
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
深入解析MFC - CString的内存结构 VC6的时候记得看过CString的源代码,并不复杂,应该是从VC7开始,MFC和ATL共用一个CString了,新的CString使用了模板技术和其它技术,值得一提。先看CString的定义:typedef CAtlString CString;如果想明确使用ANSI和UNICODE版本,可以使用CStringA和CStringW,看它们的定义:typedef CAtlStringW CStringW;typedef CAtlStringA CStringA;以上三个Atl版本的String,其定义为:typedef CStringT wchar_t, StrTraitATL CAtlStringW;typedef CStringT char, StrTraitATL CAtlStringA;typedef CStringT TCHAR, StrTraitATL CAtlString;因此,CStringT才是真实的CString类。templateclass CStringT : public CSimpleStringT BaseType, _CSTRING_IMPL_:_MFCDLLTraitsCheck:c_bIsMFCDLLTraits ;CStringT有两个模板参数,第一个表明字符类型,第二个参数从源代码中知道是StrTraitATL:template typename _BaseType = char, class StringIterator = ChTraitsOS class StrTraitATL : public StringIteratorpublic: static HINSTANCE FindStringResourceInstance(_in UINT nID) throw() return( AtlFindStringResourceInstance( nID ) ); static IAtlStringMgr* GetDefaultManager() throw() return( &g_strmgr ); ;从类声明看到他提供了一个字符串管理器,字符迭代器和从资源中获得字符串的功能。字符串管理器比较重要,后面会提到。CStringT没有成员变量,封装了很多好用的字符串函数,数据在基类CSimpleStringT中。CSimpleStringT只有一个成员变量m_pszData,不要小看这个变量,在它身上,有着很多秘密,绝对不是他的声明那么朴实:PXSTR m_pszData;PXSTR就是char或者wchar_t,只不过被模板的特化技术封装了一下。CSimpleStringT没有直接操作m_pszData,而是通过成员函数GetData来获得,看一下这个函数:CStringData* GetData() const throw() return( reinterpret_cast( m_pszData )-1 );这 个函数将m_pszData指向的内存转成CStringData类型,然后往前移动sizeof(CStringData)的长度,指向了一个 CStringData对象。m_pszData的秘密就在此处,实际上,每次分配内存时,都会多分配一段sizeof(CStringData)长度的 内存,最前面这段数据格式化为CStringData对象,然后m_pszData指向其后的数据,这才是字符串。|_|_|CStringData m_pszData再看CStringData的声明:struct CStringData IAtlStringMgr* pStringMgr; / String manager for this CStringData int nDataLength; / Length of currently used data in XCHARs (not including terminating null) int nAllocLength; / Length of allocated data in XCHARs (not including terminating null) long nRefs; / Reference count: negative = locked / XCHAR datanAllocLength+1 / A CStringData is always followed in memory by the actual array of character data;CStringData包含了这个字符串的所有信息,包括字符串长度,内存长度和引用计数,另外还有一个字符串管理器指针,这个指针从前面所提到的模板参数StrTraitATL中得到。再看看接口IAtlStringMgr的声明:_interface IAtlStringMgrpublic: / Allocate a new CStringData CStringData* Allocate( int nAllocLength, int nCharSize ) throw(); / Free an existing CStringData void Free( CStringData* pData ) throw(); / Change the size of an existing CStringData CStringData* Reallocate( CStringData* pData, int nAllocLength, int nCharSize ) throw(); / Get the CStringData for a Nil string CStringData* GetNilString() throw(); IAtlStringMgr* Clone() throw();IAtlStringMgr提供了字符串内存的分配和销毁。具体实现参考类CAfxStringMgr。 我们还是先看看一个字符串是如何赋值的吧,给下面第二行代码加上断点,调试进入:CString s;s = LHello world;一直跟踪到wmemcpy_s函数,才找到了拷贝的函数,以下是堆栈:s = LHello world;CStringT:operator=() / a CSimpleStringT:operator=() / b SetString(const wchar_t * pszSrc) / c SetString(const wchar_t * pszSrc, int nLength) / d CopyChars / e一行行来分析:a,调用基类CSimpleStringT的操作符=b,调用SetStringc,求字符串pszSrc长度,调用两个参数的SetStringd,调用GetBuffer分配内存空间,然后判断新字符串是否与现有字符串重叠,重叠调用CopyCharsOverlapped拷贝新字符串,不重叠调用CopyCharse,CopyChars就是wmemcpy_s在上面的步骤中,值得关注的GetBuffer函数。我们继续进入这个函数看看发生了什么:SetStringGetBuffer / a PrepareWrite / b PrepareWrite2 / c Fork / d CAfxStringMgr:Allocate / e _malloc_dbg / fa,调用PrepareWriteb,判断引用计数是否大于1或者长度不够,满足任意一个条件,都需要调用PrepareWrite重新分配内存,否则直接返回m_pszDatac,首先判断新申请的长度是否小于已经内存长度,如果小于,则将长度设置为已有内存长度。然后判断引用计数是否大于1,是则调用Fork重新申请内存。如果引用计数不大于1,则看是否需要申请内存,是则重新分配。重新分配有一个简单的原则,以下这段比较清楚:if( pOldData-nAllocLength nAllocLength; if( nNewLength 1024 ) nNewLength += 1024; else nNewLength *= 2; if( nNewLength nLength ) nNewLength = nLength; Reallocate( nNewLength );d,取出旧的CStringData,克隆一个IAtlStringMgr,并分配nLength长度的内存。格式化新分配的内存,并释放旧内存。注意释放的方式,并不是直接free内存,而是调用了CStringData的Release:void Release() throw() ATLASSERT( nRefs != 0 ); if( _AtlInterlockedDecrement( &nRefs ) Free( this ); 可以看到只有引用计数小于或等于0了,才会直接free内存。e,具体看代码吧:CStringData* CAfxStringMgr:Allocate( int nChars, int nCharSize ) throw() size_t nTotalSize; CStringData* pData; size_t nDataBytes; nDataBytes = (nChars+1)*nCharSize; nTotalSize = sizeof( CStringData )+nDataBytes; pData = (CStringData*)m
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 安全、文明施工方案
- 河南省漯河市郾城区2022-2023学年九年级上学期期中化学试题(含答案)
- 高电压试验基础知识培训课件
- 9Z-11E-Octadecadienoyl-CoA-9Z-11E-Octadecadienoyl-coenzyme-A-生命科学试剂-MCE
- 保险金融资格考试科目及答案
- 保险代理人分级考试题及答案
- 高桥村消防知识培训课件
- 高校无人机培训课件
- 高志谦课件教学课件
- 高尔夫球基础知识培训课件
- 骨髓炎诊断与治疗
- “满鲜一体化”视域下“满鲜”商业会议所联合会研究(1918-1929)
- 小学生AI科普课件
- 2025新食品安全法及修订解读企业应对新规培训课件
- DGJ08-70-2021 建筑物、构筑物拆除技术标准
- 新时代基础教育改革政策解读
- 中国足协D级教练员理论培训大纲
- 2025年4月自考00611日语句法篇章法试题
- 部编五年级上册语文教案全册表格版
- 儿科绪论考试题及答案
- 验光技术(第3版)课件 第七章 老视验配
评论
0/150
提交评论