我的文章可见:
http://www.csdn.net/author/adambear
真想不到之五:高效字串指针类
关键字:vb、hcak、字串指针、bstr、效率、内存共享
难度:中级或高级
参考文章:
1、2000年7月vbpj black belt专栏文章《modify a varialbe's pointer》
作者:bill mccarthy
2、1998年4月vbpj black belt专栏文章《play vb's strings》
作者:francesco balena
引言:
本想以内存共享做为vb指针专题的最后一篇,写着写着发现字串的问题应该单独谈谈。在内存共享的问题上,我尤其关心的是字串的共享,因为在我一个多月前发布的源码里用的是《hardcore vb》里bruce mckinney提供的csharestr类,它实现了字串的内存共享。但是bruce也没有突破局限,对字串的处理依然是copymemory的乾坤大挪移,尤其是还要进行讨厌的ansi/dbcs和unicode的转换。我在readme里说过它效率极低,应该采用variant或byte数组来实现,才能避免转换。后来又想到可以用strptr来做,并在vc里用dll共享节实现了可以不进行转换的字串内存共享。不过在vc里我仍然需要用sysallocstring来建立vb能使用的bstr。这都不是我想要的,我想要的东西要象vc里的cstring的一样,只要字串够大,对其赋值就不用重新分配内存,还要象vc里ccombstr类一样可以attach到一个特定bstr。
知道该怎么做,是在看了vbpj上bill mccarthy和francesco balena的两篇文章之后。bill用修改safearray描述结构实现了数组的内存共享,而francesco则对字串指针进行深入的探讨。但是bill和francesco的东西都没有实现我想要的字串类。
方法知道了,实现并不难,所以我决定自己来包装一个这样的东西。
正文:
使用vb里的字串类型string有两大不足:第一、它的分配是由vb运行时控制,我们不能将其分配在指定内存处;第二,任何一次对字串的赋值操作都要进行内存重新分配。要实现高效、灵活的字串处理,我们必须克服这两大不足。
对于第一个问题,通过修改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