VB“變態”用法之高效字串指針類
使用VB里的字串類型String有兩大不足:第一、它的分配是由VB運行時控制,我們不能將其分配在指定內存處;第二,任何一次對字串的賦值操作都要進行內存重新分配。要實現高效、靈活的字串處理,我們必須克服這兩大不足。
對于第一個問題,通過修改String變量里放著的BSTR描述符指針可以實現;對于第二個問題,可以用Mid語句(注意是語句而不是函數)來賦值。不詳細講了,直接看下面的這個類:
對于第一個問題,通過修改String變量里放著的BSTR描述符指針可以實現;對于第二個問題,可以用Mid語句(注意是語句而不是函數)來賦值。不詳細講了,直接看下面的這個類:
| Option Explicit '******************************************************** 'clsBSTR.cls '作者: 熊超 ID: AdamBear 2002年3月18日 'http://www.csdn.net/Author/AdamBear ' 你可以自由使用本類模塊,不過請保留本聲明 '******************************************************** Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long) '不要直接對sString賦值(可以用MID語句),將其設為公有僅為提高效率。 Public sString As String 'BSTR描述符指針 Private pStr As Long 'BSTR地址 Private nMaxLen As Long 'BSTR最大字節數 '讓本字串指向特定地址 Public Sub Attach(Addr As Long, Optional nLen As Long) pStr = Addr '修改BSTR描述符指針,使其指向Addr CopyMemory ByVal VarPtr(sString), Addr, 4 If IsMissing(nLen) Then Exit Sub '設定最大字串字節數 nMaxLen = nLen End Sub '還原本字串原BSTR描述符 Public Sub Detach() CopyMemory ByVal VarPtr(sString), 0&, 4 End Sub '讓本字串指向源字串 Public Sub AttachStr(sStr As String) Attach StrPtr(sStr), LenB(sStr) End Sub 'data為缺省屬性 Public Property Let data(sVal As String) Dim c As Long c = LenB(sVal) '超過最大字串數,拋出錯誤。 If c > nMaxLen Then Err.Raise vbObjectError + 3000, "CString::Let Data", "溢出" '寫字串長度 CopyMemory ByVal (pStr - 4), c, 4 '寫字串 Mid(sString, 1) = sVal End Property '可以通過公有變量sString來讀字串,效率更高 Public Property Get data() As String data = sString End Property Private Sub Class_Terminate() Call Detach End Sub |
用法如下,假設我們已通過VitualAlloc,HeapAlloc,MapViewOfFile這樣的內存管理API得到了一個4k個字節的可讀寫的內存地址baseAddr:
| Dim sShare As New clsBSTR '留下前4個字節用于BSTR保存字串字節數 sShare.Attach(baseAddr+4, 4096-4) '下面的字串"Test"會直接寫到baseAddr+4字節處 sShare = "Test" Dim y As String '讀字串時可以用sString屬性或缺省屬性 y = sShare.sString '用AttachStr方法Attach到一個字串。 '必須要先Detach sShare.Detach sShare.AttachStr(y) sShare = "Hahaha" Debug.Print y '一旦AttachStr到字串y后,對sShare的修改就相當于對y的修改。 '并且以后對y的修改也只能用Mid語句 Mid(y, 1) = "xxxxx" '不能直接賦值,這樣VB會將原來y所指(也是sShare所指)內存釋放, ' 重新分配y。這樣在訪問sShare時會出錯。 'y = "Test" |
使用這個類有幾個需要注意的地方。
1、讀字串時可以用sString屬性來讀,更快。
讀sShare有兩種方法,一種是用缺省屬性Data來讀,一種是直接用sString屬性來讀。用sString屬性不重新分配內存,要快得多。
2、不要直接給sString賦值,應使用缺省的data屬性來賦值。
之所以把sString屬性暴露出來,是為了效率和方便。我們可以用Mid語句對其進行修改,但不要直接用"="來賦值。
3、注意Attach的第二個參數,表示字串的最大字節數,不要讓它超過已經分配的內存。
4、用AttachStr將本字串對象Attach到某個字串(比如上面的y)上后,不能再對這個字串y重新賦值,也不能將其傳遞到會對其重新賦值的過程。
這么多需要注意的問題,用起來豈不是更不方便。的確,用它的之前要考慮是不是必須的。因為建立這個類也一樣有開銷。所以還有一個需要注意的問題:
5、它主要的應用還是在于將字串安放在指定內存處。雖然它也可以讓同一個進程內幾個的字串達到共享的目的,但是如果只是兩三個很小的字串這樣時做反而慢了。
后計:
數組指針和字串指針我們已經談過了,對于普通的數值類型變量的指針沒有什么Hack的必要,但是它關系到一個有用的技術,下篇文章再談。