CString 的写时复制技术?

 

        我的邮箱是 wuxfei@gmail.com,今天记录一下写时复制相关的类容。如有错误,请指正!
        众所周知,CString 是 MFC 中最风光的类之一,它给我们提供了很实用的字符串处理功能,其有一个成员变量(m_pchData)是用来存放字符串数据的。我们在使用的过程中,免不了会有 CString 对象间的相互赋。但你有没有注意到,CString 对象间相互赋值时,被赋值对象并没有立即申请内存空间来拷贝数据,而是在本 CString 对象有数据改变时,才会申请内存空间,这时才真正执行拷贝动作,拷贝完成后再执行修改动作。

 

        请看下面一段代码的执行

	CString str1 = _T("Hello");
	CString str2 = str1;
	CString str3 = str1;

	TCHAR *p;

	p =  (LPTSTR)(LPCTSTR)str1;
	p =  (LPTSTR)(LPCTSTR)str2;
	p =  (LPTSTR)(LPCTSTR)str3;

	str2.SetAt(0, 'W');

	p =  (LPTSTR)(LPCTSTR)str1;
	p =  (LPTSTR)(LPCTSTR)str2;
	p =  (LPTSTR)(LPCTSTR)str3;

        通过调试发现,str2 在未改变自身类容时,其数据地址和 str1 数据地址是相同的,在 str2.SetAt(0, 'W'); 过后,str2 的数据地址才发生改变,即才真正的申请内存空间执行拷贝。即文章开头所说的写时拷贝。CString 的这种设计方法使得其在大量对象赋值时,提高了运行效率、节省了内存空间,较为灵活。

 

 

        另外,CString 提供了两种获取内部数据地址的方法,一种是 GetBuffer()、和LPCTSTR。需要注意的是前者提供的是可写属性的,即调用此方法后,就执行了申请空间和拷贝动作;后者提供的是只读属性,它是不会触发申请空间和执行拷贝的。所以千万不要有对后者获取的地址空间进行写的动作,这样会给程序带来灾难性破坏。

        请看下面一段代码:

	CString str1 = _T("Hello");
	CString str2 = str1;
	CString str3 = str1;

	_tcscpy((LPTSTR)(LPCTSTR)str1, _T("abc"));

 

        通过调试,你就会发现在执行 _tcscpy((LPTSTR)(LPCTSTR)str1, _T("abc")); 过后,str1、str2、str3 的数据内容都是“abc”了。正确的做法是这样的:

	CString str1 = _T("Hello");
	CString str2 = str1;
	CString str3 = str1;

	_tcscpy(str1.GetBuffer(100), _T("abc"));
	str1.ReleaseBuffer();


 

 

        通过这篇文章,我们就不难理解,为什么有时候我并没有改变某个 CString 对象的数据呀,但它为什么它就随着另一个 CString 对象在变化呢!

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值