先来看看我下面的这段代码 使用上有什么问题:
m_WeatherZone = "北京";
m_szWeatherInfo = "多云转晴";
m_szWeatherglass = "23~35度";
......
......
CString WeatherZone = "";
int strLen = this->m_WeatherZone.GetLength();
memcpy(WeatherZone.GetBuffer(strLen),this->m_WeatherZone.GetBuffer(strLen),strLen);
CString
strLen = this->m_szWeatherInfo.GetLength();
memcpy(WeatherInfo.GetBuffer(strLen),this->m_szWeatherInfo.GetBuffer(strLen),strLen);
CString
strLen = this->m_szWeatherglass.GetLength();
memcpy(Weatherglass.GetBuffer(strLen),this->m_szWeatherglass.GetBuffer(strLen),strLen);
......
......
眼尖的你一定发现问题了吧,其实是我在写代码的时候太着急了 忘记了ReleaseBuffer().....
为什么没有ReleaseBuffer就会出现这样的问题呢?我都已经进行了memcpy了呀?
下面就来详细探讨下GetBuffer 和 ReleaseBuffer 的原理吧~~~~
GetBuffer:
LPTSTR CString::GetBuffer(int nMinBufLength)
{
}
参数:
指定:表示要重新申请的缓冲大小,重新申请的字符串的长度如果小于等于先前的字符串长度, 则不会重新分配内存使用原来的内存;如果大于当前字符串长度,则要重新分配缓冲,然后把旧缓冲给Release掉。
不指定:默认为0,表示缓冲大小为当前值,而且不会申请新的缓冲。
返回值:
指定并大于当前长度,返回的是新申请的缓冲的指针;
不指定或指定但小于当前长度,返回的是当前缓冲的指针。
可以基于GetBuffer返回的指针,对缓冲进行操作,从而修改CSting的内容。
由上可知,在确定对CString对象当前缓存的操作不会越界的前提下,不必指定GetBuffer的参数,之后对CString的操作都是在当前缓存上进行的;而如果可能造成越界,则必须指定一个值,此时,CString会在内部重新申请一块缓存,作为新的当前缓存。
ReleaseBuffer:
void CString::ReleaseBuffer(int nNewLength)
{
}
ReleaseBuffer的作用只是负责消除多余的缓存内容,比如通过GetBuffer(100)申请了100个字符的空间,但后续只使用了其中的50个,则此时调用ReleaseBuffer()就会将未使用的50个空间释放掉。它并不是说释放掉通过GetBuffer分配的全部缓存空间(实际上,CString目前占用的空间在CString对象释放的时候才由CString对象自动负责释放)。
同时 ReleaseBuffer还有一个很重要的作用,就是“ GetData()->nDataLength = nNewLength;”
CString对象在内存中用一个计数器来维持可用缓冲区的大小
ReleaseBuffer的作用就是更新字符串的长度。 CString内,GetLength获取字符串长度并不是动态计算的,而是在赋值操作后计算并保存在一个int变量内的,当通过GetBuffer直接修改CString时,那个int变量并不可能自动更新,于是便有了ReleaseBuffer.
SO..
1)不管是用哪种GetBuffer获得的缓存,在CString对象销毁的时候,这些缓存都会自动销毁。
2)在GetBuffer和ReleaseBuffer之间,不要调用CString的成员函数。此时得到的结果,将是不准确、不可预知的,甚至会发生访问错误。
但使用时需要注意以下问题:
通过以上学习我明白啦~ 没有经过releaseBuffer的时候虽然我已经分配了内存拷贝了值,但是 WeatherZone 、WeatherInfo、Weatherglass 的长度都还是老样子 是0呢,所以做CString的+运算 得到的值就是“” 。