mfc的cstring是字串管理類,其為了實現高效率的緩衝管理,使用了引用記數及copybeforewrite技術。這在一定程度上加大了其神秘感和理解難度。好在他的**是公開的,所以可以給我們研究它的內部實現提供條件。下面就來看看到底是如何實現的。由於不同版本的msvc其cstring實現有些許差別,下面是針對vs2003來說明的。
由於它的基礎類使用了模板技術,可以實現記憶體管理的定製,我們只研究mfc的預設記憶體管理方式。即cafxstringmgr類提供的方式。mfc在strcore.cpp定義了它的乙個全域性例項:cafxstringmgr afxstringmanager。在特性模板引數中通過
afxgetstringmanager() 將 afxstringmanager作為預設的管理物件指標。
下面從具體的**來檢視其執行機制:
如cstring str( _t("abc") );
這個語句定義了字串物件str,並初始化為"abc"。
看它到底是如何執行的吧。
首先cstring是 cstringt 的tchar字元型別版本(自適應unicode及ascii型)。
typedef atl::cstringt< tchar, strtraitmfc< tchar > > cstring;
所以它的建構函式是呼叫了
可見在建構函式使用cthis******string( stringtraits::getdefaultmanager() ) 指定了記憶體管理物件為afxstringmanager。記住這個mfc預設的記憶體管理返回的字串記憶體為空,但帶了乙個記憶體分配器,為以後的記憶體分配做準備。因為字串記憶體為空,所以後面的賦值操作將激發記憶體分配操作。
然後呼叫賦值語句
這裡又將處理轉向了基類c******string的賦值語句
下面就進入了字串賦值的實際**
可以看出它考慮了新舊字串位址的重疊問題,並做了不同處理。
其中最關鍵的函式是getbuffer(nlength);
其中if( (nshared|ntooshort) < 0 ) // if either sign bit is set (i.e. either is less than zero), we need to copy data
說明假設字串緩衝是共享的(也就是多個cstring物件共用),將激發fork( nlength );,假如記憶體太小,將進行記憶體擴大操作。
在本例中,也許大家覺得這個初始時記憶體為0,肯定進行記憶體擴大操作。但實際上進入的是fork(nlength);,因為原來初始化的預設記憶體管理器所返回的記憶體天生屬於共享的。
nrefs = 2; // never gets freed by iatlstringmgr
這裡將預設返回的記憶體的nrefs設定為2,就是初始的字串都共享原始的那個長度為0的緩衝。
下面看看fork函式如何處理:
我們看到這裡對緩衝記憶體進行了重新分配。同時對舊的緩衝呼叫release。
其中用到了預設的記憶體管理器進行記憶體分配操作
polddata->pstringmgr->clone()->allocate( nlength, sizeof( xchar ) );
這個分配操作就是內部引用計數的關鍵部分。
我們看到這裡的分配操作額外分配了cstringdata大小的資料在緩衝的前面,該資料用於對緩衝區進行引用計數。從而實現了緩衝的共享。
然後其他操作時只要涉及資料clone或釋放操作時都將對計數進行增加或減少,從而達到緩衝共享,並在不使用時能夠及時**。
MFC的CString的find的使用
名稱 cstring find 在乙個較大的 字元 串中查詢字元或子字串 int find tchar ch const int find lpctstr lpszsub const int find tchar ch,int nstart const int find lpctstr pstr,i...
MFC之CString物件的各種函式
一 mfc常用類之 string 類 1 cstring的建構函式 cstring const cstring stringsrc 將乙個已經存在的cstring 物件 stringsrc 的內容拷貝到該 cstring 物件。例如 cstring str1 t www.google.com 將常量...
關於MFC的CString 訪問越界問題
1.很多控制項可能都要使用cstring,比如ctooltipctrl.gettext 如果我一開始,m tooltip.addtool this,m str,rect,tts alwaystip 其中 m str 的長度超過256位元組,注意是位元組,如果是unicode下,那就128 tchar...