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类中对格式转换的基本介绍,尤其是在MFC中转换字符类型很有用处。
bool SetBKPicture(CString sPicPath, DWORD dwMode); //功能:设置背景是否贴图 //输入:bShow是否背景贴图, true为贴图, false为不贴图 //输出:无 //注:内部已经刷新 //王彬 20120711 bool ShowPicture...
CString GetAutherEmail(); //功能:设置字体大小 //输入:lfHeight字体大小,单位为像素,不能为负数,当为0时表示采用系统默认大小 //输出:无 //注:内部已经刷新 void SetTextHeight(LONG lfHeight = 0);...
CString FirstInput; //用于保存运算符前面的输入值 3、添加各种按钮的单击事件处理方法的函数 控件名称列表: 主对话框标识:IDD_CALC_DIALOG 关于对话框标识:IDD_ABOUTBOX 编辑框: IDC_EDIT 运算符按钮标识: ...
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...
CString GetAutherEmail(); //功能:判断输入的节点句柄是否存在 //参数:[in] hItem 节点句柄 //返回:true节点存在,false节点不存在 bool FindItemExist(HTREEITEM hItem); //功能:设置一个节点字体颜色...
#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
// 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 ...
#include<cstring> #include using namespace std; class employee { protected: char name[20]; //姓名 int individualEmpNo;//个人编号 int grade; //级别 float accumPay; //月薪总额 static int employeeNo...
需要#include <cstring> #include <string> #include 这三个head C++中MFC开发CString类转换函数大全,涵盖以下函数: CString stringtoC(string x);//string类转CString类 string Ctostring(CString x);//CString...
BOOL WINAPI ZipPackDir(CString& pFilePath, CString& mZipFileFullPath); //打包文件夹 OK BOOL WINAPI ZipPackFiles(CString &mZipFileFullPath, CString& mUnPackPath); //打包文件夹内部文件和文件夹 OK BOOL...
在MFC通信模块中经常会遇到数据类型的转换,比如会收到下位机的数据(如:10 20 30 40 64 DD ),需要在Dailog中显示'0x64'为'100 Dec',那必须先从CString >> HEX>>DEC>> CString 实行代码如下: CString readData...
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); //...
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 ...
用法代码示例创建字符串 #include "cstring.h"//....t_cstring *s = cstring_create();将初始值添加到字符串 cstring_assign(s, "This is a fake message. ");// orcstring_add(s, "This is a fake message. ");串联...
// Exe文件名 CString m_strExeName; // Bat文件名 CString m_strBatName; public: // exe的路径 CString m_strExePath; // bat的路径 CString m_strBatPath; CString m_unInstallPath; public: // ...
二、数据结构 Stu_ 结构体 struct Stu_{ CString Stu_Id; //学号 CString Stu_Name; //姓名 CString Stu_Sex; //性别 CString Stu_BirthDate; //出生年月 ... 作者: qq_33892106 日期:2018-12-28 ...
CString Line; CInternetFile* webfile=NULL;//定义一个文件对象指针 UpdateData(); if(m_Url.Left(7)!="http://")//如果地址不含HTTP类型标志则添加本地文件类型标志 读出文件前一部分,如果文件...
CString可以说是MFC中非常有用的类了,因为它可以让我们更加轻松地处理字符串。与其看别人怎么用CSring,...我基本上把CString中常用的函数都看了一遍,像GetBuffer,ReleaseBuffer,AllocBuffer等等,感觉受益匪浅。