本系列文章可見:
http://www.csdn.net/develop/list_article.asp?author=AdamBear
VB真是想不到系列之四:VB指針葵花寶典之SafeArray
關(guān)鍵字:VB、HCAK,、指針,、SafeArray、數(shù)組指針,、效率,、數(shù)組、排序
難度:中級或高級
要求:熟悉VB,,了解基本的排序算法,,會用VC更好。
引言:
上回說到,,雖然指針的運(yùn)用讓我們的數(shù)組排序在性能上有了大大的提高,,但是CopyMemory始終是我們心里一個揮之不去的陰影,因?yàn)樗€是太慢,。在C里我們用指針,,從來都是來去自如,隨心所欲,,四兩撥千斤,;而在VB里,我們用指針卻要瞻前顧后,,哪怕一個字節(jié)都要用到CopyMemory乾坤大挪移,,真累。今天我們就來看看,,能不能讓VB里的指針也能指哪兒打哪兒,,學(xué)學(xué)VB指針的凌波微步。
各位看官,,您把茶端好了,。
一、幫VB做點(diǎn)COM家務(wù)事
本系列開張第一篇里,,我就曾說過VB的成功有一半的功勞要記到COM開發(fā)小組身上,,COM可是M$公司打的一手好牌,從OLE到COM+,,COM是近十年來M$最成功技術(shù)之一,所以有必要再吹它幾句,。
COM組件對象模型就是VB的基礎(chǔ),,Varinat,、String、Current,、Date這些數(shù)據(jù)類型都是COM的,,我們用的CStr、CInt,、CSng等Cxxx函數(shù)根本就是COM開發(fā)小組寫的,,甚至我們在VB里用的數(shù)學(xué)函數(shù),COM里都有對應(yīng)的VarxxxDiv,、VarxxxAdd,,VarxxxAbs。嘿嘿,,VB開發(fā)小組非常聰明,。我們也可以說COM的成功也有VB開發(fā)小組和天下無數(shù)VB程序員的功勞,Bill大叔英明地將COM和VB捆綁在一起了,。
所以說,,學(xué)VB而不需要了解COM,你是幸福的,,你享受著VB帶給你的輕松寫意,,她把那些瑣碎的家務(wù)事都干了,但同時你又是不幸的,,因?yàn)槟銖膩矶疾辉私饽銗鄣腣B,,若有一天VB對你發(fā)了脾氣,你甚至不知該如何去安慰她,。所以,,本系列文章將拿出幾大篇來教大家如何幫VB做點(diǎn)COM方面的家務(wù)事,以備不時之需,。
想一口氣學(xué)會所有COM家務(wù)事,,不容易,今天我們先拿數(shù)組來開個頭,,更多的技術(shù)我以后再一一道來,。
二、COM自動化里的SafeArray
就象洗衣機(jī),、電飯堡,、吹塵器,VB洗衣服,、做飯,、打掃衛(wèi)生都會用到COM自動化。它包含了一切COM里通用的東西,,所有的女人都能用COM自動化來干家務(wù),,無論是犀利的VC,、溫柔的VB、還是小巧的VBScript,,她們都能用COM自動化,,還能通過COM自動化閑話家常、交流感情,。這是因?yàn)镃OM自動化提供了一種通用的數(shù)據(jù)結(jié)構(gòu)和數(shù)據(jù)轉(zhuǎn)換傳遞的方式,。而VB的數(shù)據(jù)結(jié)構(gòu)基本上就是COM自動化的數(shù)據(jù)結(jié)構(gòu),比如VB里的數(shù)組,,在COM里叫做SafeArray,。所以在VB里處理數(shù)組時我們要清楚的知道我們是在處理SafeArray,COM里的一種安全的數(shù)組,。
準(zhǔn)備下廚,,來做一道數(shù)組指針排序的菜,在看主料SafeArray的真實(shí)結(jié)構(gòu)這前,,先讓我們來了解一下C里的數(shù)組,。
在C和C++里一個數(shù)組指針和數(shù)組第一個元素的指針是一回事,如對下:
#include <iostream>
using namespace std;
int main() {
int a[10];
cout << "a = " << a << endl;
cout << "&a[0] =" << &a[0] << endl;
} ///:~
可以看到結(jié)果a和&a[0]是相同的,,這里的數(shù)組是才數(shù)據(jù)結(jié)構(gòu)里真實(shí)意義上的數(shù)組,,它們在內(nèi)存里一個接著一個存放,我們通過第一個元素就能訪問隨后的元素,,我們可以稱這樣的數(shù)組為"真數(shù)組",。但是它不安全,因?yàn)槲覀儫o法從這種真數(shù)組的指針上得知數(shù)組的維數(shù),、元素個數(shù)等非常重要的信息,,所以也無法控制對這種數(shù)組的訪問。我們可以在C里將一個二維數(shù)組當(dāng)做一維數(shù)組來處理,,我們還可以通過一個超過數(shù)組大小的索引去訪問數(shù)組外的內(nèi)存,,但這些都是極不安全的,數(shù)組邊界錯誤可以說是C里一個非常容易犯卻不易發(fā)現(xiàn)的錯誤,。
因此就有了COM里的SafeArray安全數(shù)組來解決這個問題,,在VB里我們傳遞一個數(shù)組時,傳遞的實(shí)際上COM里的SafeAraay結(jié)構(gòu)指構(gòu)的指針,,SafeAraay結(jié)構(gòu)樣子如下:
Private Type SAFEARRAY
cDims As Integer '這個數(shù)組有幾維,?
fFeatures As Integer '這個數(shù)組有什么特性?
cbElements As Long '數(shù)組的每個元素有多大,?
cLocks As Long '這個數(shù)組被鎖定過幾次,?
pvData As Long '這個數(shù)組里的數(shù)據(jù)放在什么地方?
'rgsabound() As SFArrayBOUND
End Type
緊接在pvData這后的rgsabound是個真數(shù)組,所以不能在上面的結(jié)構(gòu)里用VB數(shù)組來聲明,,記住,,在VB里的數(shù)組都是SafeArray,,在VB里沒有聲明真數(shù)組的方法,。
不過這不是問題,因?yàn)樯厦鍿FArrayBOUND結(jié)構(gòu)的真數(shù)組在整個SAFEARRAY結(jié)構(gòu)的位置是不變的,,總是在最后,,我們可以用指針來訪問它。SFArrayBOUND數(shù)組的元素個數(shù)有cDims個,,每一個元素記錄著一個數(shù)組維數(shù)的信息,,下面看看它的樣子:
Private Type SAFEARRAYBOUND
cElements As Long '這一維有多少個元素?
lLbound As Long '它的索引從幾開始,?
End Type
還有一個東西沒說清,,那就是上面SAFEARRAY結(jié)構(gòu)里的fFeatures,它是一組標(biāo)志位來表示數(shù)組有那些待性,,這些特性的標(biāo)志并不需要仔細(xì)的了解,,本文用不上這些,后面的文章用到它們時我會再來解釋,。
看了上面的東西,,各位一定很頭大,好在本文的還用不了這么多東西,,看完本文你就知道其實(shí)SafeArray也不難理解,。先來看看如下的聲明:
Dim MyArr(1 To 8, 2 To 10) As Long
這個數(shù)組做為SafeArray在內(nèi)存里是什么樣子呢?如圖一:
cDims = 2 | fFeatures = FADF_AUTO AND FADF_FIXEDSIZE | 位置 0 |
cbElements = 4 LenB(Long) | 4 |
cLocks = 0 | 8 |
pvData(指向真數(shù)組) | 12 |
rgsabound(0).cElements = 8 | 16 |
rgsabound(0).lLbound = 1 | 18 |
rgsabound(1).cElements = 9 | 22 |
rgsabound(1).lLbound = 2 | 26 |
cDims = 2 |
fFeatures = FADF_AUTO AND FADF_FIXEDSIZE | 位置 0 |
cbElements = 4 LenB(Long) | 4 |
cLocks = 0 | 8 |
pvData(指向真數(shù)組) | 12 |
rgsabound(0).cElements = 8 | 16 |
rgsabound(0).lLbound = 1 | 18 |
rgsabound(1).cElements = 9 | 22 |
rgsabound(1).lLbound = 2 |
26 |
圖一 :SafeArray內(nèi)存結(jié)構(gòu)
cDims表示它是個2維數(shù)組,,sFeatures表示它是一個在堆棧里分配的固定大小的數(shù)組,,cbElements表示它的每個元素大小是Long四個字節(jié),pvData指向真的數(shù)組(就是上面說的C里的數(shù)組),,rgsabound這個真數(shù)組表明數(shù)組二個維的大小和每個維的索引開始位置值,。
先來看看從這個上面我們能做些什么,比如要得到一個數(shù)組的維數(shù),,在VB里沒有直接提供這樣的方法,,有一個變通的方法是通過錯誤捕獲如下:
On Error Goto BoundsError
For I = 1 To 1000 '不會有這么多維數(shù)的數(shù)組
lTemp = LBound(MyArr, I)
Next
BoundErro:
nDims = I - 1
MsgBox "這個數(shù)組有" & nDims & "維"
現(xiàn)在我們知道了SafeArray的原理,所以也可以直接得到維數(shù),,如下:
'先得到一個指向SafeArray結(jié)構(gòu)的指針的指針,,原理是什么,我后面說,。
ppMyArr = VarPtrArray(MyArr)
'從這個指針的指針得到SafeArray結(jié)構(gòu)的指針
CopyMemory pMyArr, ByVal ppMyArr, 4
'再從這個指針?biāo)傅刂返念^兩個字節(jié)取出cDims
CopyMemory nDims, ByVal pMyArr, 2
MsgBox "這個數(shù)組有" & nDims & "維"
怎么樣,,是不是也明白了LBound實(shí)際上是SafeArray里的rgsabound的lLbound,而UBound實(shí)際上等于lLbound +cElements - 1,,現(xiàn)在我提個問,,下面iUBound應(yīng)該等于幾,?
Dim aEmptyArray() As Long
iUBound = UBound(aEmptyArray)
正確的答案是-1,不奇怪,,lLbound -cElements - 1 = 0 - 0 - 1 = -1
所以檢查UBound是不是等于-1是一個判斷數(shù)組是不是空數(shù)組的好辦法,。
還有SafeArray結(jié)構(gòu)里的pvData指向存放實(shí)際數(shù)據(jù)的真數(shù)組,它實(shí)際就是一個指向真數(shù)組第一個元素的指針,,也就是說有如下的等式:
pvDate = VarPtr(MyArr(0))
在上一篇文章里,,我們傳給排序函數(shù)的是數(shù)組第一個元素的地址VarPtr(xxxx(0)),也就是說我們傳的是真數(shù)組,,我們可以直接在真數(shù)組上進(jìn)行數(shù)據(jù)的移動,、傳遞。但是要如何得到一個數(shù)組SafeArray結(jié)構(gòu)的指針呢,?你應(yīng)該注意到我上面所用的VarPtrArray,,它的聲明如下:
Declare Function VarPtrArray Lib "msvbvm60.dll" _
Alias "VarPtr" (Var() As Any) As Long
它就是VarPtr,只不過參數(shù)聲明上用的是VB數(shù)組,,這時它返回來的就是一個指向數(shù)組SafeArray結(jié)構(gòu)的指針的指針,。因?yàn)閂arPtr會將傳給它的參數(shù)的地址返回,而用ByRef傳給它一個VB數(shù)組,,如前面所說,,實(shí)際上傳遞的是一個SafeArray結(jié)構(gòu)的指針,這時VarPtrArray將返回這個指針的指針,。所以要訪問到SafeArray結(jié)構(gòu)需要,,如下三步:
用VarPtrArray返回ppSA,再通過ppSA得到它指向的pSA,,pSA才是指向SafeArray結(jié)構(gòu)的指針,,我們訪問SafeArray結(jié)構(gòu)需要用到就是這個pSA指針。
現(xiàn)在你應(yīng)該已經(jīng)了解了SafeArray大概的樣子,,就這么一點(diǎn)知識,,我們就能在VB里對數(shù)組進(jìn)行HACK了。
三,、HACK數(shù)組字串指針
這已經(jīng)是第三篇講指針的東西了,,我總在說指針能夠讓我們怎么樣怎么樣,不過你是不是覺得除了我說過的幾個用途外,,你也沒覺得它有什么用,,其實(shí)這是因?yàn)槲液痛蠹乙粯蛹庇谇蟪伞T谥v下去之前,,我再來理一理VB里指針應(yīng)該在什么情況下用,。
只對指針類型用指針!廢話?我的意思是說,,象Integer, Long, Double這樣的數(shù)值類型它們的數(shù)據(jù)直接存在變量里,,VB處理它們并不慢,沒有HACK的必要,。但是字串,以及包括字串,、數(shù)組,、對象、結(jié)構(gòu)的Variant,,還有包括字串、對象結(jié)構(gòu)的數(shù)組它們都是指針,,實(shí)際數(shù)據(jù)不放在變量里,,變量放的是指針,由于VB不直接支持指針,,對他們的操作必須連同數(shù)據(jù)拷貝一起進(jìn)行,。有時我們并不想賦值,我們只想交換它們指針,,或者想讓多個指針指向同一個數(shù)據(jù),,讓多個變量對同一處內(nèi)存操作,要達(dá)到這樣的目的,,在VB里不HACK是不行的,。
對數(shù)組尤其如此,比如我們今天要做的菜:對一個字串?dāng)?shù)組進(jìn)行排序,。我們知道,,對字串?dāng)?shù)組進(jìn)行排序很大一部分時間都用來交換字串元素,在VB里對字串賦值時要先將原字串釋放掉,,再新建一個字串,,再將源字串拷貝過來,非常耗時,。用COM里的概念來說,,比如字串a(chǎn)、b的操作a=b,,要先用SysFreeString(a)釋放掉原來的字串a(chǎn), 再用a = SysAllocString(b)新建和拷貝字串,,明白了這一點(diǎn)就知道,在交換字串時不要用賦值的方式去交換,,而應(yīng)該直接去交換字串指針,,我在指針葵花寶典第一篇里介紹過這種交換字串的方法,這可以大大提高交換字串的速度。但是這種交換至少也要用兩次CopyMemory來將指針寫回去,,對多個字串進(jìn)行交換時調(diào)用CopyMemory的次數(shù)程幾何增長,,效率有很大的損失。而實(shí)際上,,指針只是32位整數(shù)而已,,在C里交換兩個指針,只需要進(jìn)行三次Long型整數(shù)賦值就行了,。所以我們要想想我們能不能將字串?dāng)?shù)組里所有字串指針拿出來放到一個Long型指針數(shù)組里,,我們只交換這個Long型數(shù)組里的元素,也就相當(dāng)于交換了字串指針,,排好序后,,再將這個Long型指針數(shù)組重新寫回到字串?dāng)?shù)組的所有字串指針里,而避免了多次使用CopyMemory來一次次兩兩交換字串指針,。這樣我們所有的交換操作都是對一個Long型數(shù)組來進(jìn)行,,要知道交換兩個Long型整數(shù),在VB里和在C里是一樣快的,。
現(xiàn)在我們的問題成了如何一次性地將字串?dāng)?shù)組里的字串指針拿出來,,又如何將調(diào)整后的字串指針數(shù)組寫回去。
不用動數(shù)組的SafeArray結(jié)構(gòu),,我們用StrPtr也能完成它,。我們知道,字串?dāng)?shù)組元素里放的是實(shí)際上是字串指針,,也就是BSTR指針,,把這些指針放到一個Long型數(shù)組里很簡單,用下面的方法:
Private Sub GetStrPtrs()
Dim Hi As Long, Lo As Long
Hi = UBound(MyArr)
Lo = LBound(MyArr)
ReDim lStrPtrs(0 To 1, Lo To Hi) As Long
Dim i As Long
For i = Lo To Hi
lStrPtrs(0, i) = StrPtr(MyArr(i)) 'BSTR指針數(shù)組
lStrPtrs(1, i) = i '原數(shù)組索引
Next
End Sub
為什么要用2維數(shù)組,,這是排序的需要,,因?yàn)楫?dāng)我們交換lStrPtrs里的Long型指針時,原來的字串?dāng)?shù)組MyArr里的字串指針并沒有同時交換,,所以用lStrPtrs里的Long型指針訪問字串時,,必須通過原來的索引,因此必須用2維數(shù)組同時記錄下每個Long型指針?biāo)缸执谠执當(dāng)?shù)組里的索引,。如果只用1維數(shù)組,,訪問字串時就又要用到CopyMemory了,比如訪問lStrPtrs第三個元素所指的字串,,得用如下方法:
CopyMemory ByVal VarPtr(StrTemp), lStrPtrs(3), 4
雖然只要我們保證StrTemp足夠大,,再加上一些清理善后的工作,這種做法是可以的,,但實(shí)際上我們也看到這樣還是得多次調(diào)用CopyMemory,,實(shí)際上考慮到原來的字串?dāng)?shù)組MyArr一直就沒變,,我們能夠通過索引來訪問字串,上面同樣的功能現(xiàn)在就成了:
StrTemp = MyArr(lStrPtrs(1,3)) '通過原字串?dāng)?shù)組索引讀出字串,。
不過,,當(dāng)我們交換lStrPtrs里的兩個Long型指針元素時,還要記得同時交換它們的索引,,比如交換第0個和第3個元素,,如下:
lTemp1 = lStrPtrs(0, 3) : lTemp2 = lStrPtrs(1, 3)
lStrPtrs(0, 3) = lStrPtrs(0, 0) : lStrPtrs(1, 3) = lStrPtrs(1, 0)
lStrPtrs(0, 0) = lTemp1 : lStrPtrs(1, 0) = lTemp2
當(dāng)我們排好序后,我們還要將這個lStrPtrs里的指針元素寫回去,,如下:
For i = Lo To Hi
CopyMemory(ByVal VarPtr(MyArr(i)), lStrPtrs(0,i), 4)
Next
我已經(jīng)不想再把這個方法講下去,,雖然它肯定可行,并且也肯定比用CopyMemory來移動數(shù)據(jù)要快,,因?yàn)槲覀儗?shí)際上移動的僅僅是Long型的指針元素,。但我心里已經(jīng)知道下面有更好更直接的方法,這種轉(zhuǎn)彎抹角的曲線救國實(shí)在不值得浪費(fèi)文字,。
四,、HACK數(shù)組的BSTR結(jié)構(gòu),實(shí)時處理指針,。
最精采的來了,實(shí)時處理指針動態(tài)交換數(shù)據(jù),,好一個響亮的說法,。
我們看到,上一節(jié)中所述方法的不足在于我們的Long型指針數(shù)組里的指針是獨(dú)立的,,它沒有和字串?dāng)?shù)組里的字串指針聯(lián)系在一起,,要是能聯(lián)系在一起,我們就能在交換Long型指針的同時,,實(shí)時地交換字串元素,。
這可能嗎?
當(dāng)然,,否則我花那么筆墨去寫SafeArray干什么,!
在上一節(jié),我們的目的是要把字串?dāng)?shù)組里的BSTR指針數(shù)組拿出來放到一個Long型數(shù)組里,,而在這一節(jié)我們的目的是要讓我們Long型指針數(shù)組就是字串?dāng)?shù)組里的BSTR指針數(shù)組,。拿出來再放回去的方法,我們在上一節(jié)看到了,,現(xiàn)在我們來看看,,不拿出來而直接用的方法。
這個方法還是要從字串?dāng)?shù)組的SafeArray結(jié)構(gòu)來分析,,我們已經(jīng)知道SafeArray結(jié)構(gòu)里的pvData指向的就是一個放實(shí)際數(shù)據(jù)的真數(shù)組,,而一個字串?dāng)?shù)組如MyArr它的pvData指向的是一個包含BSTR指針的真數(shù)組?,F(xiàn)在讓我們想想,如果我們將一個Long型數(shù)組lStrPtrs的pvData弄得和字串?dāng)?shù)組MyArr的pvData一樣時會怎樣,?BSTR指針數(shù)組就可以通過Long型數(shù)組來訪問了,,先看如何用代碼來實(shí)現(xiàn)這一點(diǎn):
'模塊級變量
Private MyArr() As String '要排序的字串?dāng)?shù)組
Private lStrPtrs() As Long '上面數(shù)組的字串指針數(shù)組,后面會憑空構(gòu)造它
Private pSA As Long '保存lStrPtrs數(shù)組的SafeArray結(jié)構(gòu)指針
Private pvDataOld As Long '保存lStrPtrs數(shù)組的SafeArray結(jié)構(gòu)的原
' pvData指針,,以便恢復(fù)lStrPtrs
'功能: 將Long型數(shù)組lStrPtrs的pvData設(shè)成字串?dāng)?shù)組MyArr的pvData
' 以使Long指針數(shù)組的變更能實(shí)時反應(yīng)到字串?dāng)?shù)組里
Private Sub SetupStrPtrs()
Dim pvData As Long
' 初始化lStrPtrs,,不需要將數(shù)組設(shè)得和MyArr一樣大
' 我們會在后面構(gòu)造它
ReDim lStrPtrs(0) As Long
'得到字串?dāng)?shù)組的pvData
pvData = VarPtr(MyArr(0))
'得到lStrPtrs數(shù)組的SafeArray結(jié)構(gòu)指針
CopyMemory pSA, ByVal VarPtrArray(lStrPtrs), 4
'這個指針偏移12個字節(jié)后就是pvData指針,將這個指針保存到pvDataOld
' 以便最后還原lStrPtrs,,此處也可以用:
' pvDataOld = VarPtr(lStrPtrs(0))
CopyMemory pvDataOld, ByVal pSA + 12, 4
'將MyArr的pvData寫到lStrPtrs的pvData里去
CopyMemory ByVal pSA + 12, pvData, 4
'完整構(gòu)造SafeArray必須要構(gòu)造它的rgsabound(0).cElements
CopyMemory ByVal pSA + 16, UBound(MyArr) - LBound(MyArr) + 1, 4
'還有rgsabound(0).lLbound
CopyMemory ByVal pSA + 20, LBound(MyArr), 4
End Sub
看不懂,,請結(jié)合圖一再看看,應(yīng)該可以看出我們是憑空構(gòu)造了一個lStrPtrs,,使它幾乎和MyArr一模一樣,,唯一的不同就是它們的類型不同。MyArr字串?dāng)?shù)組里的fFeatures包含F(xiàn)ADF_BSTR,,而lStrPtrs的fFeatures包含F(xiàn)ADF_HAVEVARTYPE,,并且它的VARTYPE是VT_I4。不用關(guān)心這兒,,我們只要知道lStrPtrs和MyArr它們指向同一個真數(shù)組,,管他是BSTR還是VT_I4,我們把真數(shù)組里的元素當(dāng)成指針來使就行了,。
注意,,由于lStrPtrs是我們經(jīng)過了我們很大的改造,所以當(dāng)程序結(jié)束前,,我們應(yīng)該將它還原,,以便于VB來釋放資源。是的,,不釋放也不一定會引起問題,,因?yàn)槌绦蜻\(yùn)行結(jié)束后,操作系統(tǒng)的確是會回收我們在堆棧里分配了卻沒有釋放的lStrPtrs原來的野指針pvOldData,,但當(dāng)你在IDE中運(yùn)行時,,你有60%的機(jī)會讓VB的IDE死掉。我們是想幫VB做點(diǎn)家務(wù)事,,而不是想給VB添亂子,,所以請記住在做完菜后,一定要把廚房打掃干凈,,東西該還原的一定要還原,。下面看看怎么樣來還原:
'還原我們做過手腳的lStrPtr
Private Sub CleanUpStrPtrs()
'lStrPtr的原來聲明為:ReDim lStrPtrs(0) As Long
' 按聲明的要求還原它
CopyMemory pSA, ByVal VarPtrArray(lStrPtrs), 4
CopyMemory ByVal pSA + 12, pvDataOld, 4
CopyMemory ByVal pSA + 16, 1, 4
CopyMemory ByVal pSA + 20, 0, 4
End Sub
好了,精華已經(jīng)講完了,,如果你還有點(diǎn)想不通,,看看下面的實(shí)驗(yàn):
'實(shí)驗(yàn)
Sub Main()
'初始化字串?dāng)?shù)組
Call InitArray(6)
'改造lStrPtrs
Call SetupStrPtrs
'下面說明兩個指針是一樣的
Debug.Print lStrPtrs(3)
Debug.Print StrPtr(MyArr(3))
Debug.Print
'先看看原來的字串
Debug.Print MyArr(0)
Debug.Print MyArr(3)
Debug.Print
'現(xiàn)在來交換第0個和第3個字串
Dim lTmp As Long
lTmp = lStrPtrs(3)
lStrPtrs(3) = lStrPtrs(0)
lStrPtrs(0) = lTmp
'再來看看我們的字串,,是不是覺得很神奇
Debug.Print MyArr(0)
Debug.Print MyArr(3)
Debug.Print
'還原
Call CleanUpStrPtrs
End Sub
在我的機(jī)器上,運(yùn)行結(jié)果如下:
1887420
1887420
OPIIU
WCYKOTC
WCYKOTC
OPIIU
怎么樣,?如愿已償,!字串通過交換Long型數(shù)被實(shí)時交換了。
通過這種方式來實(shí)現(xiàn)字串?dāng)?shù)組排序就非??炝?,其效率上的提高是驚人的,對冒泡排序這樣交換字串次數(shù)很多的排序方式,,其平均性能能提高一倍以上(要看我們字串平均長度,,),對快速排序這樣交換次數(shù)較少的方法也能有不少性能上的提高,,用這種技術(shù)實(shí)現(xiàn)的快速排序,,可以看看本文的配套代碼中的QSortPointers。
本道菜最關(guān)鍵的技術(shù)已經(jīng)講了,,至于怎么做完這道菜,,怎么把這道菜做得更好,還需要大家自己來實(shí)踐,。
四,、我們學(xué)到了什么。
僅就SafeArray來說,,你可能已經(jīng)發(fā)現(xiàn)我根本就沒有直接去用我定義了的SAFEARRAY結(jié)構(gòu),,我也沒有展開講它,實(shí)際上對SafeArray我們還可以做很多工作,,還有很多巧妙的應(yīng)用。還有需要注意的,,VarPtrArray不能用來返回字串?dāng)?shù)組和Variant數(shù)組的SafeArray結(jié)構(gòu)的指針的指針,,為什么會這樣和怎樣來解決這個問題?這些都需要我們了解BSTR,,了解VARIANT,,了解VARTYPE,這些也只是COM的冰山一角,,要學(xué)好VB,,乃至整個軟件開發(fā)技術(shù),COM還有很多很多東西需要學(xué)習(xí),,我也還在學(xué),,在我開始COM的專題之前,大家也應(yīng)該自學(xué)一下,。
COM的東西先放一放,,下一篇文章,,應(yīng)朋友的要求,我準(zhǔn)備來寫寫內(nèi)存共享,。
后記:
又花了整整一天的時間,,希望寫的東西有價值,覺得有用就來叫個好吧,!
AdamBear
熊超
[email protected]