CString的GetBuffer用法

一.函数原型

CString::GetBuffer

LPTSTR GetBuffer( int nMinBufLength );

throw( CMemoryException );

Return Value

An LPTSTR pointer to the object’s (null-terminated) character buffer.

Parameters

nMinBufLength

The minimum size of the character buffer in characters. This value does not include space for a null terminator.

Remarks

Returns a pointer to the internal character buffer for the CString object. The returned LPTSTR is notconst and thus allows direct modification of CString contents.

If you use the pointer returned by GetBuffer to change the string contents, you must callReleaseBuffer before using any other CString member functions.

二.函数作用及使用范围

对一个CString变量,你可以使用的唯一合法转换符是LPCTSTR,直接转换成非常量指针(LPTSTR-[const] char*)是错误的。正确的得到一个指向缓冲区的非常量指针的方法是调用GetBuffer()方法。

GetBuffer()主要作用是将字符串的缓冲区长度锁定,releaseBuffer则是解除锁定,使得CString对象在以后的代码中继续可以实现长度自适应增长的功能。

CString ::GetBuffer有两个重载版本:

LPTSTR GetBuffer( );LPTSTR GetBuffer(int nMinBufferLength);

在第二个版本中,当设定的长度小于原字符串长度时,nMinBufLength = nOldLen,该参数会被忽

略,不分配内存,指向原CString;当设定的长度大于原字符串本身的长度时就要重新分配(reallocate)一块比较大的空间出来。而调用第一个版本时,应如通过传入0来调用第二个版本一样。

是否需要在GetBufer后面调用ReleaseBuffer(),是根据你的后面的程序是否需要继续使用该字符串变量,并且是否动态改变其长度而定的。如果你GetBuffer以后程序自函数就退出,局部变量都不存在了,调用不调用ReleaseBuffer没什么意义了。

最典型的应用就是读取文件:

CFile file;

// FILE_NAME 为实现定义好的文件名称

if(file.Open(FILE_NAME,CFile::modeRead))

{

CString szContent;

int nFileLength = file.GetLength();

file.Read(szContent.GetBuffer(nFileLength),nFileLength);

szContent.ReleaseBuffer();

// 取得文件內容放在szContent中,我们之后可以对其操作

}

三.测试

以下就CString::GetBuffer,做简单测试:

测试1:

// example for CString::GetBuffer

#include <stdio.h>

#include <afx.h>

void main(void)

{

CString s( "abcd" );

printf("(1)before GetBuffer:\n");

printf("CString s.length=%d\n",s.GetLength());

printf("CString s=%s\n",s);

LPTSTR p = s.GetBuffer( 2 );

printf("(2)after GetBuffer and before ReleaseBuffer:\n");

printf("LPTSTR p=%s\n",p);

printf("p.length=%d\n",strlen(p));

printf("CString s=%s\n",s);

printf("CString s.length=%d\n",s.GetLength());

s.ReleaseBuffer( );

printf("(3)after ReleaseBuffer:\n");

printf("LPTSTR p=%s\n",p);

printf("p.length=%d\n",strlen(p));

printf("CString s=%s\n",s);

printf("CString s.length=%d\n",s.GetLength());

}

测试结果1:

(1)before GetBuffer:

CString s.length=4

CString s=abcd

(2)after GetBuffer and before ReleaseBuffer:

LPTSTR p=abcd

p.length=4

CString s=abcd

CString s.length=4

(3)after ReleaseBuffer:

LPTSTR p=abcd

p.length=4

CString s=abcd

CString s.length=4

Press any key to continue

测试2:

将LPTSTR p = s.GetBuffer( 2 ); 修改为:LPTSTR p = s.GetBuffer( 10 );

测试结果同1。

测试3:

在测试二的LPTSTR p = s.GetBuffer( 10 );后添加  p[5]='f';

测试结果同1。

测试4:

将测试三的p[5]='f';修改为p[4]='e';

测试结果4:

(1)before GetBuffer:

CString s.length=4

CString s=abcd

(2)after GetBuffer and before ReleaseBuffer:

LPTSTR p=abcde屯屯?

p.length=10

CString s=abcde屯屯?

CString s.length=4

(3)after ReleaseBuffer:

LPTSTR p=abcde屯屯?

p.length=10

CString s=abcde屯屯?

CString s.length=10

Press any key to continue

很显然(2)after GetBuffer and before ReleaseBuffer:中 CString s.length=4结果有问题。

注意:以上测试是在_MBCS环境下,如果换成_UNICODE则结果有可能不同。

参考:

《CString GetBuffer()》

http://blog.csdn.net/hbyh/archive/2007/09/15/1786574.aspx

《CString之GetBuffer问题》

http://game.tongji.net/thread-379834-1-1.html

《CString的GetBuffer》

http://www.programfan.com/blog/article.asp?id=40755

《CString GetBuffer() and ReleaseBuffer()》

http://blog.csdn.net/guanchanghui/archive/2006/09/13/1217096.aspx

《CString::GetBuffer()与CString::ReleaseBuffer到底有什么用?》

http://topic.csdn.net/t/20060313/22/4612156.html

====================================================================================================================

转载:http://blog.pfan.cn/xman/43212.html

GetBuffer()主要作用是将字符串的缓冲区长度锁定,releaseBuffer则是解除锁定,使得CString对象在以后的代码中继续可以实现长度自适应增长的功能。

CString ::GetBuffer有两个重载版本:

LPTSTR GetBuffer( );LPTSTR GetBuffer(int nMinBufferLength);

在第二个版本中,当设定的长度小于原字符串长度时,nMinBufLength = nOldLen,该参数会被忽

略,不分配内存,指向原CString;当设定的长度大于原字符串本身的长度时就要重新分配(reallocate)一块比较大的空间出来。而调用第一个版本时,应如通过传入0来调用第二个版本一样。

是否需要在GetBufer后面调用ReleaseBuffer(),是根据你的后面的程序是否需要继续使用该字符串变量,并且是否动态改变其长度而定的。如果你GetBuffer以后程序自函数就退出,局部变量都不存在了,调用不调用ReleaseBuffer没什么意义了。

这是一个非常容易被用错的函数,主要可能是由于大家对它的功能不太了解。其实点破的话,也不是那么深奥。
    GetBuffer(int size)是用来返回一个你所指定大小可写内存的成员方法。它和被重载的操作符LPCTSTR还是有点本质区别的,LPCTSTR是直接返回一个只读内存的指针,而GetBuffer则是返回一个可以供调用者写入的内存,并且,你可以给定大小。下面是个简单的,但也是非常典型的例子:
    int readFile(CString& str, const CString& strPathName)
    {
        FILE* fp = fopen(strPathName, "r"); // 打开文件
        fseek(fp, 0, SEEK_END);
        int nLen = ftell(fp); // 获得文件长度
        fseek(fp, 0, SEEK_SET); // 重置读指针
        char* psz = str.GetBuffer(nLen);
        fread(psz, sizeof(char), nLen, fp); //读文件内容
        str.ReleaseBuffer(); //千万不能缺少
        fclose(fp);
    }
    上面的函数是GetBuffer函数最典型的用法了,其实它就相当于申请一块nLen大小的内存,只不过,这块内存是被引用在CString对象的内部而已,这是非常有效的一种用法,如果不直接用GetBuffer函数来申请的话,那么你必须用new操作符(或者malloc()函数)在CString的外部申请,然后再将申请的内存拷贝到CString对象中,显然这是一个非常冗余的操作,会使你函数的效率大大下降。
    ReleaseBuffer函数是用来告诉CString对象,你的GetBuffer所引用的内存已经使用完毕,现在必须对它进行封口,否则 CString将不会知道它现在所包含的字符串的长度,所以在使用完GetBuffer之后,必须立即调用ReleaseBuffer函数重置 CString的内部属性,其实也就是头部信息。

补充一下:

GetBuffer说白了就两个功能:

1:就是将CString里面的内存交到外部一个来处理,外部可以直接修改它的内容。

2:重新修改CString的内存大小,这个数值不包含null结尾符。

另一个典型的用法:就是将CString里面的内容变为int或long型,需要先获取里面的内存指针。这样就可以先GetBuffer(内存大小)方便直接转换。

如果在外部修改了CString里面的内容,在重新使用CString之前,需调用ReleaseBuffer()也就是说,ReleaseBuffer不需要每次都调用。

MSDN原文:

If you use the pointer returned by GetBuffer to change the string contents, you must call ReleaseBuffer before using any other CSimpleStringTmember methods.

The buffer memory is automatically freed when the CSimpleStringT object is destroyed.

If you keep track of the string length yourself, you should not append the terminating null character. You must, however, specify the final string length when you release the buffer with ReleaseBuffer. If you do append a terminating null character, you should pass –1 (the default) for the length toReleaseBuffer, and ReleaseBuffer will perform a strlen on the buffer to determine its length.

=========================================================================================================================

CString str = "abcde\0cde";
输出字符串的值为: abcde

而字符串的长度为 s.GetLength() 的值为: 5

这是因为CString对象在赋值时只检查到'\0',后面的忽略了, 也就是说实际对象str内容为"abcde".

而str真正的存储空间为6(字符串以'\0'结尾).

所以说在字符长度和实际的空间是不一样的. 好!别跑!

请看下面有趣的程序:

CString str = "hello";

LPSTR pf = (LPSTR)(LPCSTR)s;

LPSTR pa = s.GetBuffer(0);

你可以测得 pf == pa;

LPSTR pb = s.GetBuffer(10);

你可以测得 pf != pb;

为什么:

我们都知道(LPSTR)(LPCSTR)s 实际指向对象str的实际字符串的内存地址, GetBuffer() 函数中的参数(其实就是重新申请的字符串的长度)如果小于等于先前的字符串长度, 则不会重新分配内存使用原来的内存所以 pf == pa, 如果大于先前的字符串长度, 则重新追加内存(也就是要复制原来的内容),

所以pf != pb.

注意GetBuffer()函数中的参数为重新申请的字符串的长度, 实际内存的大小应再加1.

CString s = "hello";

LPSTR pf = s.GetBuffer(0);

strcpy(pf,"hi");

这时对象str 的内容为 "hi"

但是s.GetLength()的值为5, 如果加上一条语句:

s.ReleaseBuffer();

则s.GetLength()的值为2

解释: 
CString对象在内存中用一个计数器来维持可用缓冲区的大小

void ReleaseBuffer( int nNewLength = -1 )
     {
          if( nNewLength == -1 )
          {
               nNewLength = StringLength( m_pszData );
          }
          SetLength( nNewLength );
     }

很明显ReleaseBuffer的作用就是更新字符串的长度。 CString内,GetLength获取字符串长度并不是动态计算的,而是在赋值操作后计算并保存在一个int变量内的,当通过GetBuffer直接修改CString时,那个int变量并不可能自动更新,于是便有了ReleaseBuffer.

CString s = "hello";

LPSTR pf = s.GetBuffer(0);

strcpy(pf,"hi");

LPSTR ps =  (LPSTR)(LPCSTR)s;    字符串缓冲区的首地址

*(ps+2) = 'x';

则字符串的实际内容为:    "hixlo"

*(ps+6) = 'a';        出错, 因为对象s的实际空间为 6

CString s = "hello";

LPSTR pf = s.GetBuffer(10);

strcpy(pf,"hi");

LPSTR ps =  (LPSTR)(LPCSTR)s;    字符串缓冲区的首地址

*(ps+2) = 'x';

*(ps+5)= '\0';

则字符串的实际内容还是为:    "hixlo"

*(ps+6) = 'a';         可以因为s对象的实际空间为11

说白了  ReleaseBuffer就是更新赋值之后的字符串的长度, 而实际空间没有根本的变化, GetBuffer才是使内存空间大小变化的罪魁祸首.

转载:http://blog.sciencenet.cn/blog-481152-427173.html

精解CString类的GetBuffer,ReleaseBuffer 函数(VC++)相关推荐

  1. Visual Studio/MFC编程入门之MFC常用类:CString类

    上一节讲了分割窗口的有关知识,本节开始讲解MFC的一些常用类,先来说说CString类.在内容开始前为大家介绍一款MFC界面开发控件: Xtreme Toolkit Pro | 免费下载:是屡获殊荣的 ...

  2. CString类所有成员函数详解

    VC里CString是我们最常用的类之一,我们觉得对它很熟悉了,可是你知道它的所有用法吗? 还是系统的学习一下吧,认真看完本文就OK了. 下面开始: CString::Compare int Comp ...

  3. MFC CString GetBuffer/ReleaseBuffer 的使用条件

    今天为了通过串口往单片机里写一个16进制字符去控制单片机的adc的起停,结果糊涂到把'\x01'误写成'\0x01',怎么也得不到意想的结果,程序员有时候会犯低级错误,有时候怎么也跳不出去,这时候通过 ...

  4. JavaScript 编程精解 中文第三版 三、函数

    三.函数 原文:Functions 译者:飞龙 协议:CC BY-NC-SA 4.0 自豪地采用谷歌翻译 部分参考了<JavaScript 编程精解(第 2 版)> 人们认为计算机科学是天 ...

  5. Getbuffer ReleaseBuffer Cstring

    getbuffer是为了让你使用CString类中,保存字符串缓冲区的那块指针.     至于releasebuffer,在MSDN中有这样一句话.     If   you   use   the ...

  6. MFC CString的GetBuffer()/ReleaseBuffer()

    CString GetBuffer()/ReleaseBuffer()两个方法的使用 LPTSTR GetBuffer(int nMinBufLength); void ReleaseBuffer(i ...

  7. MFC CString GetBuffer ReleaseBuffer方法

    一.函数原型 CString::GetBuffer LPTSTR GetBuffer( int nMinBufLength ); throw( CMemoryException ); Return V ...

  8. MFC常用类、成员函数、数组类、Cstring类、CTime类、CPoint类

    MFC数组类CByteArray: CDWordArray: CPtrArray: CUIntArray: CWordArray: CStringArray: 常用成员函数 1.int Add( AR ...

  9. 【STL】string详解(string类常用的操作函数、构造函数、赋值操作、子符串的拼接、查找和替换、比较、存取、插入和删除、获取)

    目录 1. string容器 简介 2. string类常用的操作函数 3. 构造函数 4. 赋值操作 5. 字符串拼接 6. 字符串查找和替换 7. 字符串比较 8. 字符串存取 9. 字符串插入和 ...

最新文章

  1. python拆分excel的sheet为单文件_python拆分Excel表格并发送邮件
  2. 【微信小程序之画布】终:手指触摸画板实现
  3. 记录下log4j的两种配置方式
  4. bat 脚本清空窗口内容_tomcat9.0启动脚本startup.bat的分析
  5. Oracle手边常用70则脚本知识汇总
  6. qt获取QString中第一个汉字
  7. 15_实现浏览器记录
  8. CentOS 7.6虚拟机ping: www.baidu.com: Name or service not known
  9. 智慧水务技能——SWMM、最优化与预测理论及三维动态可视化
  10. RK3568-ANDROID11-4G-EC20-驱动篇(移远模块)
  11. linux执行telnet命令,Linux怎么使用telnet命令
  12. python调用手机摄像头识别二维码_JS调用安卓手机摄像头扫描二维码
  13. python将数据导入数据库 atomic_Python3 连接 Sqlite3
  14. win10/11如何安装安卓app?带你使用华为移动应用引擎
  15. 微信小程序开发实战(网络请求设置)
  16. 让Qt程序适配高分辨率屏幕,解决软件界面错乱异常
  17. android管理交换机,适用于Android的Visual Studio模拟器 – 运行模拟设备需要内部虚拟网络交换机...
  18. 苹果三代耳机_华强北airpods2 华强北三代耳机 airpodspro可调通透 主动降噪 定位改名 苹果airpodspro...
  19. 计算机硬件配置无法启动,因计算机磁盘硬件的配置问题,windows无法启动 急!急!急!...
  20. oracle 数据库安装选项,Oracle 11g数据库安装及配置

热门文章

  1. “全球反盗版日”,向盗版发动猛烈攻击
  2. 计算机系大学生的未来在何方
  3. 淘宝Native研发模式的演进与思考 | DX研发模式
  4. css文本字体形状_使用CSS更改文本字体
  5. js如何用touchstart+touchend实现长按事件
  6. Comparator详解
  7. 短信平台源码销售短信路由流程—移讯云短信系统
  8. 功能实现思路、逻辑思路、功能、逻辑
  9. IP 的一百种创意玩法,是育碧的套路没错了!
  10. 墨者学院布尔盲注(超详细手工和工具)