深入解析cstring的内存结构

上传人:第*** 文档编号:32759157 上传时间:2018-02-12 格式:DOC 页数:5 大小:40KB
返回 下载 相关 举报
深入解析cstring的内存结构_第1页
第1页 / 共5页
深入解析cstring的内存结构_第2页
第2页 / 共5页
深入解析cstring的内存结构_第3页
第3页 / 共5页
深入解析cstring的内存结构_第4页
第4页 / 共5页
深入解析cstring的内存结构_第5页
第5页 / 共5页
亲,该文档总共5页,全部预览完了,如果喜欢就下载吧!
资源描述

《深入解析cstring的内存结构》由会员分享,可在线阅读,更多相关《深入解析cstring的内存结构(5页珍藏版)》请在金锄头文库上搜索。

1、深入解析 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,其

2、定义为:typedef CStringT CAtlStringW;typedef CStringT CAtlStringA;typedef CStringT CAtlString;因此,CStringT 才是真实的 CString 类。templateclass CStringT : public CSimpleStringT:c_bIsMFCDLLTraits ;CStringT 有两个模板参数,第一个表明字符类型,第二个参数从源代码中知道是 StrTraitATL:template class StrTraitATL : public StringIteratorpublic:static

3、 HINSTANCE FindStringResourceInstance(_in UINT nID) throw()return( AtlFindStringResourceInstance( nID ) ); static IAtlStringMgr* GetDefaultManager() throw()return( ;从类声明看到他提供了一个字符串管理器,字符迭代器和从资源中获得字符串的功能。字符串管理器比较重要,后面会提到。CStringT 没有成员变量,封装了很多好用的字符串函数,数据在基类CSimpleStringT 中。CSimpleStringT 只有一个成员变量 m_ps

4、zData,不要小看这个变量,在它身上,有着很多秘密,绝对不是他的声明那么朴实: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(CStringDat

5、a)的长度,指向了一个 CStringData 对象。m_pszData 的秘密就在此处,实际上,每次分配内存时,都会多分配一段 sizeof(CStringData)长度的 内存,最前面这段数据格式化为 CStringData 对象,然后 m_pszData 指向其后的数据,这才是字符串。|_|_|CStringData m_pszData再看 CStringData 的声明:struct CStringDataIAtlStringMgr* pStringMgr; / String manager for this CStringDataint nDataLength; / Length o

6、f 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 charac

7、ter data;CStringData 包含了这个字符串的所有信息,包括字符串长度,内存长度和引用计数,另外还有一个字符串管理器指针,这个指针从前面所提到的模板参数StrTraitATL 中得到。再看看接口 IAtlStringMgr 的声明:_interface IAtlStringMgrpublic:/ Allocate a new CStringDataCStringData* Allocate( int nAllocLength, int nCharSize ) throw();/ Free an existing CStringDatavoid Free( CStringData*

8、 pData ) throw();/ Change the size of an existing CStringDataCStringData* Reallocate( CStringData* pData, int nAllocLength, int nCharSize ) throw(); / Get the CStringData for a Nil stringCStringData* GetNilString() throw();IAtlStringMgr* Clone() throw();IAtlStringMgr 提供了字符串内存的分配和销毁。具体实现参考类CAfxString

9、Mgr。 我们还是先看看一个字符串是如何赋值的吧,给下面第二行代码加上断点,调试进入:CString s;s = LHello world;一直跟踪到 wmemcpy_s 函数,才找到了拷贝的函数,以下是堆栈:s = LHello world;CStringT:operator=() / aCSimpleStringT:operator=() / bSetString(const wchar_t * pszSrc) / cSetString(const wchar_t * pszSrc, int nLength) / dCopyChars / e一行行来分析:a,调用基类 CSimpleStr

10、ingT 的操作符=b,调用 SetStringc,求字符串 pszSrc 长度,调用两个参数的 SetStringd,调用 GetBuffer 分配内存空间,然后判断新字符串是否与现有字符串重叠,重叠调用 CopyCharsOverlapped 拷贝新字符串,不重叠调用 CopyCharse,CopyChars 就是 wmemcpy_s在上面的步骤中,值得关注的 GetBuffer 函数。我们继续进入这个函数看看发生了什么:SetStringGetBuffer / aPrepareWrite / bPrepareWrite2 / cFork / dCAfxStringMgr:Allocate

11、 / e_malloc_dbg / fa,调用 PrepareWriteb,判断引用计数是否大于 1 或者长度不够,满足任意一个条件,都需要调用PrepareWrite 重新分配内存,否则直接返回 m_pszDatac,首先判断新申请的长度是否小于已经内存长度,如果小于,则将长度设置为已有内存长度。然后判断引用计数是否大于 1,是则调用 Fork 重新申请内存。如果引用计数不大于 1,则看是否需要申请内存,是则重新分配。重新分配有一个简单的原则,以下这段比较清楚:if( pOldData-nAllocLength nAllocLength;if( nNewLength 1024 )nNewLe

12、ngth += 1024;elsenNewLength *= 2;if( nNewLength 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*)malloc( nTotalSize );if (pData = NULL)return NULL;pData-pStringMgr = this;pData-nRefs = 1; pData-nAllocLength = nChars;pData-nDataLength = 0; return pData;可以看到实际分配的内存大小是字符串长度+1 个 NULL+sizeof(CStringData)f,分配内存

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 建筑/环境 > 工程造价

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号