原文
memutils库提供了一套根据不同域调整以提升性能的4个增强型分配器.新的赋值语法带来了许多好处,包括可轻松替换分配器.
1,AppMem:AppMem分配器通过原垃集传输,但已整合以支持新语法,并建议手动管理.如果禁止了DebugAlllocator,自动垃集会通过该分配器工作,但它不会调用任何显式的析构器.
2,ThreadMem:该分配器针对线本堆分配微调了下,不会因锁或垃集的额外压力而变慢.
3,SecureMem:保存敏感数据如私有证书,密码或键时,CryptoSafe分配器在释放内存后清零来增强安全性,并且可选地可用一个在崩溃或系统休息/休息时不会转储到磁盘的内存池(SecurePool).
4,Alloc!T:用PoolStack覆盖GC,或如果没有可用的池则回退到新.
对分配器友好的容器有:
1,向量:一个数组.
2,数组:一个引用计数向量(允许容器共享物主).
3,HashMap:一个哈希映射.
4,HashMapRef:一个引用计数的哈希映射(允许容器共享物主).
5,RBTree:一棵红黑树.
6,DictionaryList:类似C++中的MultiMap,但,按线性搜索数组实现.
对分配器友好的生命期管理对象包括:
1,引用计数:类似C++中的共针,也兼容接口转换.
2,Unique:类似C++中的独针,默认会当作按新创建的对象,但如果指定自定义分配器,则会用.释放free在同一分配器中删除分配的对象指针.
3,ScopedPool:在域结束前给PoolStack添加一个池,允许在调用分配,在创建外的任何地方时覆盖GC分配.
引用计数对象使用了一个新的可在memutils.helpers中找到的可用来替换alias this m_obj;习语的插件模板.它允许底层对象的代理操作(包括重载符号).
推导类型无法在opApply等方法中使用的回调代理中工作,但它提供了与基接口最类似的体验.
示例:
structMyString{mixin Embed!m_obj;//该对象模拟串!string m_obj;//`自定义`方法扩展了"串"基类型的特性!voidtoInt(){}}voidmain(){string ms=MyString.init;//隐性转换也有效MyString ms2=MyString("Hello");//可用`"opStar()"`解引用"`底层对象`assert(is(typeof(*ms2)==string));}可用AppMem,ThreadMem,SecureMem来分配数组或对象!
A a=ThreadMem.alloc!A();//用`"A"`干活ThreadMem.free(a);ubyte[]ub=AppMem.alloc!(ubyte[])(150);assert(ub.length==150);向量容器和其他所有容器一样,拥有底层数据的所有权.
string val;string gcVal;{|Vector!chardata;//`默认`使用`线本分配器``(LocklessFreeList)`|data~="Hello there";|val=data[];//使用`opslice[]`符号访问底层数组.|gcVal=data[].idup;//把它移进垃集,来转义未知域!}assert(gcVal=="Hello there");writeln(val);//段错误:收集了`数据`!(这是件好事.)数组类型是RefCounted!(向量),它允许哈希映射有部分所有权,因为标记了@disable this(this)的对象与容器不兼容.
{HashMap!(string,Array!char)hmap;hmap["hey"]=Array!(char)("Hello there!");assert(hmap["hey"][]=="Hello there!");}使用GC(AppMem)处理容器时,默认仍调用free(),如果你想让数据出域,必须复制它.
string gcVal;{Vector!(char,AppMem)data;data~="Hello there";gcVal=data[].idup;}assert(gcVal=="Hello there");唯一Unique的生命期管理对象默认拥有GC分配的内存.当内存出域时,它会显式释放内存,并且按对象成员工作!
classA{inta;}A a=newA;{Unique!A=a;}assert(a is null);更多示例见source/tests.d.