Getbuffer ReleaseBuffer Cstring

來源:互聯網
上載者:User

  getbuffer是為了讓你使用CString類中,儲存字串緩衝區的那塊指標.  
  至於releasebuffer,在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.  
  在對GetBuffer返回的指標使用之後需要調用ReleaseBuffer,這樣才能使用其他Cstring的operations。否則會發生錯誤.

 首先舉個例子。CString s( "abcd" );
int len=s.GetLength();
LPTSTR p = s.GetBuffer( 5 );
strcpy( p, "Hello" );

這是 GetBuffer 的第一種用法,也是最簡單的一種,不用給它傳遞參數,它使用預設值 0,意思是:“給我這個字串的指標,我保證不加長它”。當你調用 ReleaseBuffer 時,字串的實際長度會被重新計算,然後存入 CString 對象中。

如果你需要修改 CString 中的內容,它有一個特殊的方法可以使用,那就是 GetBuffer,它的作用是返回一個可寫的緩衝指標。

如果僅僅是讀出CString中的內容,那麼只需要用GetBuffer(0)即可。如果後面對CString還有其他動作,那麼立刻ReleaseBuffer。

其他:
GetBuffer() 他會create出所指定大小的空間出來 這個空間是可以讓我們修改的
很多時候 有的 API 會要一個(char*)的指標作為輸出
如果我們就因為這樣去產生一個(char*)的buffer 給他 等到資料取出來之後
便無法使用CString 的種種方便功能
因此 比較好的做法 便是用GetBuffer()來產生一個buffer空間給他
等到取出來之後 我們便可以直接使用CString來對他操作
GetBuffer() 使用完後 最好是呼叫一下ReleaseBuffer()做為結束

雖然小弟的網誌之前已經有很多GetBuffer()的使用了 不過還是附個範例
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中 我們之後可以對其操作
}

關於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)這樣的常數,實際中的程式不可能是這麼容易事Crowdsourced Security Testing道的,所以也就有了
strTest.GetBuffer(strTest.GetLength()
)的寫法.其實,GetBuffer(0)就可以了.可以由GetBuffer的源碼得到驗證.

2

    CString strTest 

=
 
"
123 45
"

;


    
//
some other code




    CString strTest2 
=

 strTest;//之後兩個cstring內容仍然存於同一記憶體位置


    
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);

CString   類裡面有專門的結構體來記錄這些資訊  
  struct   CStringData  
  {  
  long   nRefs;   //   reference   count     引用計數  
  int   nDataLength;   //   length   of   data   (including   terminator)     資料長度  
  int   nAllocLength;   //   length   of   allocation       記憶體配置長度  
  //   TCHAR   data[nAllocLength]  
   
  TCHAR*   data()   //   TCHAR*   to   managed   data  
  {   return   (TCHAR*)(this+1);   }  
  };  
   
  賦值的時候只是簡單的把引用計數加1,     nRefs++,然後指向同一記憶體單元  
  每一個對象銷毀時,先把引用計數減1,     nRefs--,然後判斷是否為0,如果為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的重要性.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.