两张图讲透Rust
仅有的两类动态分派胖指针
trait Object
胖指针
切片胖指针
与普通指针相比的特别之处
内存占用的体量不同
相较于单usize
大小的普通指针,胖指针(i.e. Wide References
)同时占用了两个usize
宽度。此特点在上两张图中已非常具象化了。
内存寻址方式不同
普通指针是先寻址到‘变量值’,再根据变量值中引用的‘类型信息’,确定
- 待调用‘成员方法’的内存位置,或
- ‘数组’的长度 — 数据长度是数组类型定义的一部分,是完全静态的属性值,不可在运行时被动态修改。
所以,普通指针对被引用值的数据结构一无所知,但变量值自备了它的‘类型信息’。
另一方面,胖指针对被引用值的数据结构有部分了解,所以无须变量值自带‘类型信息’,并能绕过‘类型信息’
- 直接调用
trait Object
上的成员方法。览阅由胖指针内第二个usize
值引用的vtable
,每个trait method
实现函数的内存偏移量一目了然。 - 直接对切片做边界检查、索引计算、甚至读取全部数据,因为切片长度就保存于胖指针内的第二个
usize
值里。
就效果而言,借助胖指针,‘变量值’与‘类型信息’之间的强关联关系妥善被解耦了。这就是“Rust
能够模仿OOP
语言,从多个互不相容的类型定义中,归纳出共有interface
契约”的技术基石:
- 以
trait Trait
作为对若干相似类型定义struct Type
中共有trait method
集合的统一描述 — 这就不需要知道每个类的具体‘类型信息’了。 - 以每个
dyn Trait
所独有的vtable
为“路引”,寻址被调用trait method
的具体实现函数。
完美!
总结
类型 | 组成部分 | 元数据含义 | 动态分派方式 |
---|---|---|---|
dyn Trait |
数据指针 + vtable |
trait method 地址表 |
运行时查vtable ,寻址trait method 具体实现函数 |
slice |
数据指针 + 长度 | 元素个数 | 运行时的边界检查与索引计算 |
结束语
此次分享的关键是文章最开始的两张图。但对Rust
内存寻址方式有所了解,才能提高Rust
编程的首次成功率,减少rustc
报警的次数。
1
共 0 条评论, 1 页
评论区
写评论还没有评论