关于GetBuffer/ReleaseBuffer,网上比较流行的一种说法是:如果你要直接修改CString的内部数据,就要调用GetBuffer/ReleaseBuffer.我也同意这样的表述.
下面是几个例子,主要是错误的例子,来加深理解.
1
CString strTest = "123";
char* p = strTest.GetBuffer(0);
int i = atoi(p);
strTest.ReleaseBuffer(); 这种用法当然没有错,但是我认为这里的GetBuffer/ReleaseBuffer是没有必要的,为什么呢?因为
int __cdecl atoi(const char *) 的参数是const char*,CString的内部数据肯定不会被修改的.
所以上面的代码可以直接写成
CString strTest = "123";
int i = atoi((LPCTSTR)strTest); 顺便说一下GetBuffer的参数问题,网上的例子中,很多都是GetBuffer(5) GetBuffer(10)这样的常数,实际中的程序不可能是这么容易事先知道的,所以也就有了strTest.GetBuffer(strTest.GetLength() )的写法.其实,GetBuffer(0)就可以了.可以由GetBuffer的源码得到验证.
2
CString strTest = "123 45";
//some other code
CString strTest2 = strTest;
char seps[] = " ";
char* pToken = 0;
//char* pStr = strTest2.GetBuffer(0);
pToken = strtok((char*)(LPCTSTR)strTest2, seps);
//pToken = strtok(pStr, seps);
while(pToken)
pToken = strtok(NULL, seps);
//strTest2.ReleaseBuffer(0); 运行上面的代码,可以看到strTest的值也变了,呵呵,这就是程序中一些关与CString的奇怪问题的起源.如果用注释中的GetBuffer/ReleaseBuffer方法,就一点问题也没有了.
同样,对于ReleaseBuffer的参数,缺省的是-1,但是我不建议.因为-1表示使用当前的00结束符位置来确定新的长度.而上面的例子中,strtok是会重新设置00结束符的,所以,安全的做法,就是把这个CString的长度设为0,ReleaseBuffer(0),反正它的内容已经变了,也没有人要用了.
说明一下,GetBuffer/ReleaseBuffer方法只能保证strTest不变,strTest2还是会变的.所以,对于一个成员变量,比如m_strTest2调用ReleaseBuffer要多一个心眼,局部变量就不用想这么多了.
那么怎么从最开始就意识到程序写错了呢?上面代码中
(char*)(LPCTSTR)是很危险的,把const去掉了,否则strtok是编译不过的,也从一个侧面说明了const的重要性.