积极答复者
ReleaseBuffer 有什么用呢?

问题
-
程序代码:
#include "u_def.h" #include <stdio.h> #include <afx.h> // #include "u_linearStruct.h" int main( int ac, char **av ) { char *pstr = NULL; CString strIn("zhong"); pstr = strIn.GetBuffer(0); printf("0:%s\n", pstr); pstr = strIn.GetBuffer(1); printf("1:%s\n", pstr); strIn.ReleaseBuffer(); printf("ReleaseBuffer:%s\n", pstr); strIn += "yunde"; printf("+ :%s\n", pstr); strIn.ReleaseBuffer(); printf("+ ReleaseBuffer:%s\n", pstr); return 0; }
1)在CString变量的长度发生变化的时候,其内存地址均会被reallocated了,
也就是ReleaseBuffer不管是否调用一次,pstr的地址都不会有效了,那为什么在MSDN上说
使用了GetBuffer再执行其他的操作前需要嗲用ReleaseBuffer
2)发现strIn.GetBuffer(0);和strIn.GetBuffer(1);得到相同的返回值,那这个参数有什么用呢 ?
清钟沁桐
答案
-
GetBuffer,ReleaseBuffer是用来做类似:strncpy(s.GetBuffer(1024),"xxxxx",1024);
这样的事情的。因为很多c api需要char*作为输出。
所以使用GetBuffer(X)能得到一个临时的最大长度为X的char*指针。
ReleaseBuffer并不是释放内存,而是查找这个临时的buffer中\0的位置,以确定字符长的长度
1.GetBuffer返回的指针是临时的,不是让你保存着一直使用的。
2.当内部的buffer比较大,GetBuffer(0) GetBuffer(1)都可以使用这个buffer。
- 已标记为答案 vfdff 2011年2月24日 18:05
全部回复
-
CString::CString()
{
Init();
}
_AFX_INLINE void CString::Init()
{ m_pchData = afxEmptyString.m_pchData; }
重新分配一块内存,把原来的数据拷贝过去,释放原来的内存.
LPTSTR CString::GetBuffer(int nMinBufLength)
{
....
// we have to grow the buffer
CStringData* pOldData = GetData();
int nOldLen = GetData()-> nDataLength; // AllocBuffer will tromp it
if (nMinBufLength < nOldLen)
nMinBufLength = nOldLen;
AllocBuffer(nMinBufLength);
memcpy(m_pchData, pOldData-> data(), (nOldLen+1)*sizeof(TCHAR));
GetData()-> nDataLength = nOldLen;
String::Release(pOldData);
....
}
如果缓冲区没有被引用,则直接将要设置长度的最后一位置零.
void CString::ReleaseBuffer(int nNewLength)
{
CopyBeforeWrite(); // just in case GetBuffer was not called
if (nNewLength == -1)
nNewLength = lstrlen(m_pchData); // zero terminated
ASSERT(nNewLength <= GetData()-> nAllocLength);
GetData()-> nDataLength = nNewLength;
m_pchData[nNewLength] = '\0 ';
}
GetBuffer和ReleaseBuffer函数是为了解决使用strcpy时字符串会超过缓冲区大小的情况. LPCTSTR 重载操作符获得的字符串指针不能作为左值修改其中数据,因为这有可能引起指针越界或使该指针无效.所以要使用Getbuffer和ReleaseBuffer
如下:
CString str;
str = "abcdef ";
//strcpy(LPCTSTR(str), "1234567890 ");是行不通的.
LPTSTR pStr = str.GetBuffer(16); //如果不重新分配的话,可能造成 //指针越界
lstrcpy(pStr, "1234567890 ");
str.ReleaseBuffer(5); //释放缓冲到指定的字符串长度
现在的字符串是 "12345 "
麻烦把正确答案设为解答。 -
GetBuffer,ReleaseBuffer是用来做类似:strncpy(s.GetBuffer(1024),"xxxxx",1024);
这样的事情的。因为很多c api需要char*作为输出。
所以使用GetBuffer(X)能得到一个临时的最大长度为X的char*指针。
ReleaseBuffer并不是释放内存,而是查找这个临时的buffer中\0的位置,以确定字符长的长度
1.GetBuffer返回的指针是临时的,不是让你保存着一直使用的。
2.当内部的buffer比较大,GetBuffer(0) GetBuffer(1)都可以使用这个buffer。
- 已标记为答案 vfdff 2011年2月24日 18:05
-
Returns a pointer to the internal character buffer for the CString object. The returned LPTSTR is not const and thus allows direct modification of CString contents。
CString::GetBuffer返回一个指向内部缓冲区的指针,你允许你修改该CString对象。
CString strText(_T("Hello,World"));
int len = strText.GetLength(); // 这里得到是长度是11
如果你修改这里面的内容.
TCHAR* pText = strText.GetBuffer(len);
_tcscpy(pText, _T("ABC"));
上面你修改了pText指向的内容了,注意:但是这里你没用调用strText.ReleaseBuffer();
AfxMessageBox(strText); // 可以看到strText的内容已经修改为"ABC"了。
len = strText.GetLenth(); // 这里的长度仍然是11,而不是修改以后的3
如果你修改以后,加上strText.RleaseBuffer();后面就正确了,MSDN里有这么一句话
If you use the pointer returned by GetBuffer to change the string contents, you must call ReleaseBuffer before using any other CString member functions.
-
CString strText(_T("Hello,World"));
CString strMsg(_T(""));
int len = strText.GetLength(); // 这里得到的长度是11
strMsg.Format(_T("1: %d"), len);
AfxMessageBox(strMsg);
//修改缓冲区的内容
TCHAR* pText = strText.GetBuffer(len);
_tcscpy(pText, _T("ABC"));
//strText.ReleaseBuffer(); // 注意这里,有和没有的区别,如果没有加这句的话AfxMessageBox(strText);显示的ABC,但是最后的AfxMessageBox(strMsg);显示还是11,
AfxMessageBox(strText);strMsg.Format(_T("2: %d"), strText.GetLength());
AfxMessageBox(strMsg);