`
jgsj
  • 浏览: 962913 次
文章分类
社区版块
存档分类
最新评论

CString::GetBuffer/ReleaseBuffer 技术内幕

 
阅读更多

CString采用copy-on-write机制(可以实现多个对象共享一块内存),高效而节省内存。

CString只有一个成员变量,长度为4,即 sizeof(CString) == 4:

class CString
{
    // functions ...
    protected:
        LPTSTR m_pchData;   // pointer to ref counted string data
    // functions ...
};

CString 使用结构体CStringData来管理数据:

struct CStringData
{
	long nRefs;             // reference count
	int nDataLength;        // length of data (including terminator)
	int nAllocLength;       // length of allocation
	// TCHAR data[nAllocLength]

	TCHAR* data()           // TCHAR* to managed data
		{ return (TCHAR*)(this+1); }
};

该结构体长度为12,有三个变量:

1、nRefs,CString的引用个数;

2、nDataLength,为字符串的长度,长度不算最后一个结束符'\0',也不包括CStringData结构体的长度12字节;

3、nAllocLength,为字符串开辟缓存的长度,不包括CStringData结构体的长度12字节;

源码说明一切:

nLen = strlen(...);
 new BYTE[sizeof(CStringData) + (nLen+1)*sizeof(TCHAR)];
nAllocLength = nLen;

而CString的成员变量m_pchData指针并不指向缓存的起始位置,而是指向该连续缓存的第13个字节处,恰巧就是字符串区域。
进一步,从CString的成员变量m_pchData向前偏移12个字节,恰巧就是CStringData结构体。这个结构体的nRefs为copy-on-write机制提供了保障,nDataLength仅仅就是记录字符串的长度,nAllocLength为了管理短小字符串,提高效率,如下:

		if (nLen <= 64)
		{
			pData = (CStringData*)_afxAlloc64.Alloc();
			pData->nAllocLength = 64;
		}
		else if (nLen <= 128)
		{
			pData = (CStringData*)_afxAlloc128.Alloc();
			pData->nAllocLength = 128;
		}
		else if (nLen <= 256)
		{
			pData = (CStringData*)_afxAlloc256.Alloc();
			pData->nAllocLength = 256;
		}
		else if (nLen <= 512)
		{
			pData = (CStringData*)_afxAlloc512.Alloc();
			pData->nAllocLength = 512;
		}


GetBuffer函数遇到下面两种情况之一时会创建一个新对象给调用者:
1、有大于1个的引用时(也就是有多个对象共享内存时);
2、GetBuffer传递的参数nMinBufLength大于原始原始分配长度时,删除原来缓存,开辟更大的缓存。

GetBuffer返回一个字符串指针,可以像操作 TCHAR* 一样操作,并立即反映到CString对象中。

ReleaseBuffer可以理解为重新设置CString的字符串有效长度。(当然ReleaseBuffer也考虑到了多个对象共享的情况,它不会设置其共享对象的长度。最好不要在TCHAR* p = GetBuffer之后再引用该对象,此时p指向了所有共享对象的字符串内存。)

ReleaseBuffer做了两个动作:
1、多个对象共享时,启用copy-on-write机制,新建一个对象。
2、重新设置CString的有效长度。

所以,在调用GetBuffer之后,如果没有共享,并且不需要重新设置有效长度(没有更改字符),完全可以不调用ReleaseBuffer。

exemple:

   CString str0 = "abcdefghijklmnopqrstuvwxyz";
   CString str1 = str0;
   char* p = str0.GetBuffer(0);
   CString str2 = str0;
   p[0] = '1';
   p[1] = '2';
   p[2] = '3';
   p[3] = '4';
   p[4] = '5';
   str0.ReleaseBuffer(5);


执行完之后的结果:
str0 {"12345"}
str1 {"abcdefghijklmnopqrstuvwxyz"}
str2 {"12345fghijklmnopqrstuvwxyz"}

分享到:
评论

相关推荐

    CString::Format函数详细介绍

    CString::Format函数详细介绍,这个文档详细介绍了CString类中对格式转换的基本介绍,尤其是在MFC中转换字符类型很有用处。

    重载静态文本控件CStatic,支持背景贴图和透明,v1.1

    bool SetBKPicture(CString sPicPath, DWORD dwMode); //功能:设置背景是否贴图 //输入:bShow是否背景贴图, true为贴图, false为不贴图 //输出:无 //注:内部已经刷新 //王彬 20120711 bool ShowPicture...

    重载静态文本控件CStatic,支持背景贴图和透明,v1.2

    CString GetAutherEmail(); //功能:设置字体大小 //输入:lfHeight字体大小,单位为像素,不能为负数,当为0时表示采用系统默认大小 //输出:无 //注:内部已经刷新 void SetTextHeight(LONG lfHeight = 0);...

    计算器 mfc 代码

    CString FirstInput; //用于保存运算符前面的输入值 3、添加各种按钮的单击事件处理方法的函数 控件名称列表: 主对话框标识:IDD_CALC_DIALOG 关于对话框标识:IDD_ABOUTBOX 编辑框: IDC_EDIT 运算符按钮标识: ...

    Super string 库

    int CString_numberStr_2_int(CString str); int stdString_2_int(std::string str);//std string 字符串转int int std_hexString_2_int(std::string str);//std string 字符串转int double CString_2_double...

    重载树控件CTreeCtrl,v1.1

    CString GetAutherEmail(); //功能:判断输入的节点句柄是否存在 //参数:[in] hItem 节点句柄 //返回:true节点存在,false节点不存在 bool FindItemExist(HTREEITEM hItem); //功能:设置一个节点字体颜色...

    visual c++课程设计出租车管理系统源程序

    #if !defined(AFX_LAWDLG_H__02236AFB_C27A_4D09_81CD_443DD9944D76__INCLUDED_) ... CString m_strDepartment; CString m_strMoney; CString m_strName; CString m_strNO; CString m_strPoint; //}}AFX_DATA

    一个跨平台的CString源码

    // make it as forgiving as CString's version is. Thanks to // Igor Kholodov for noticing this. // - Added a specialization of std::swap for CStdString. Thanks // to Mike Crusader for ...

    c++源码,一个工资管理系统

    #include&lt;cstring&gt; #include using namespace std; class employee { protected: char name[20]; //姓名 int individualEmpNo;//个人编号 int grade; //级别 float accumPay; //月薪总额 static int employeeNo...

    C++中MFC开发CString类转换函数大全

    需要#include &lt;cstring&gt; #include &lt;string&gt; #include 这三个head C++中MFC开发CString类转换函数大全,涵盖以下函数: CString stringtoC(string x);//string类转CString类 string Ctostring(CString x);//CString...

    zip dll and code

    BOOL WINAPI ZipPackDir(CString& pFilePath, CString& mZipFileFullPath); //打包文件夹 OK BOOL WINAPI ZipPackFiles(CString &mZipFileFullPath, CString& mUnPackPath); //打包文件夹内部文件和文件夹 OK BOOL...

    MFC 数值转换 CString >> HEX>>DEC>> CString

    在MFC通信模块中经常会遇到数据类型的转换,比如会收到下位机的数据(如:10 20 30 40 64 DD ),需要在Dailog中显示'0x64'为'100 Dec',那必须先从CString &gt;&gt; HEX&gt;&gt;DEC&gt;&gt; CString 实行代码如下: CString readData...

    VC.NET MusicPlayer播放器源码.rar

     CString CSimplyPlayerDlg::GetMusicInfo(CString m_Path, CString strIndex);  //以假设的128kbps帧频率速度来计算mp3的时间  CString GetAboutMusicTime( CString m_Path );  //获得MP3歌曲的精确时间,但...

    学生选课系统

    CString m_password; //}}AFX_DATA // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CAddAdmini_dlg) protected: virtual void DoDataExchange(CDataExchange* pDX); //...

    CHtmlView访问文件内部资源与innerHTML

    CString s; s.Format("res://%s.exe/%d", ::AfxGetAppName(), IDR_HTML1); Navigate2(s); } 2、innerHTML操作内存中的HTML void CInerHTMLView::OnTest() { // TODO: Add your command handler code here ...

    cstring:简单的 C 字符串操作函数

    用法代码示例创建字符串 #include "cstring.h"//....t_cstring *s = cstring_create();将初始值添加到字符串 cstring_assign(s, "This is a fake message. ");// orcstring_add(s, "This is a fake message. ");串联...

    C++卸载程序功能示例

     // Exe文件名 CString m_strExeName;  // Bat文件名 CString m_strBatName; public:  // exe的路径 CString m_strExePath;  // bat的路径 CString m_strBatPath;  CString m_unInstallPath; public:  // ...

    Socket通信.rar

    二、数据结构 Stu_ 结构体 struct Stu_{ CString Stu_Id; //学号 CString Stu_Name; //姓名 CString Stu_Sex; //性别 CString Stu_BirthDate; //出生年月 ... 作者: qq_33892106 日期:2018-12-28 ...

    VC 使用WinInet通过HTTP协议读取网上文件.rar

     CString Line;  CInternetFile* webfile=NULL;//定义一个文件对象指针  UpdateData();  if(m_Url.Left(7)!="http://")//如果地址不含HTTP类型标志则添加本地文件类型标志  读出文件前一部分,如果文件...

    CString实现的源代码

    CString可以说是MFC中非常有用的类了,因为它可以让我们更加轻松地处理字符串。与其看别人怎么用CSring,...我基本上把CString中常用的函数都看了一遍,像GetBuffer,ReleaseBuffer,AllocBuffer等等,感觉受益匪浅。

Global site tag (gtag.js) - Google Analytics