当前位置:网站首页>rust中的静态分发和动态分发
rust中的静态分发和动态分发
2022-07-21 09:07:00 【pilaf1990】
rust中的范型属于静多态,它是编译时多态,无运行时性能损耗。在编译时,不论是范型枚举、范型函数还有范型结构体,都会被单态化(Monomorphization)。
以下面的范型函数为例:
fn main() {
let foo = Foo;
static_dispatch(&foo);
dynamic_dispatch(&foo);
}
#[derive(Debug)]
struct Foo;
trait Bar {
fn baz(&self);
}
impl Bar for Foo {
fn baz(&self) {
println!("{:?}", self);
}
}
// 静态分发
fn static_dispatch<T>(t: &T) where T: Bar {
t.baz();
}
// 动态分发
fn dynamic_dispatch(t: &dyn Bar) {
t.baz();
}
static_dispatch范型函数在编译的时候,会找到Bar trait的所有实现,并为它们分别生成一个实现,比如上面的示例中,只有Foo一个结构体实现了Bar trait,那么其实在编译期static_dispatch会生成
fn static_dispatch(t: &Foo){
t.baz();
}
这个方法,如果还有其它的Bar trait实现还会生成它对应的具体方法。即在编译的时候就会将每个Bar trait的实现都生成一个具体方法,运行的时候就无开销了。
将上述方法放到https://play.rust-lang.org/上选择ASM:
可以看到生成的编译后的代码中确实是单态化了的:
而dynamic_dispatch的方法入参是t:&dyn Bar
,是一种动态分发。参数t标注的类型&Bar是trait对象。trait本身也是一种抽象而非具体的类型,但它的类型大小在编译期是无法确定的,所以trait对象必须使用胖指针。可以利用引用操作符&或Box<T>来制造一个trait对象。
trait对象等价于下面的结构体:
pub struct TraitObject{
pub data: *mut(),
pub vtable: *mut(),
}
TraitObject包括两个指针:data指针和vtable指针。以impl MyTrait for T
为例,data指针指向trait对象保存的类型数据T,vtable指针指向包含为T实现的MyTrait的vtable(virtual table,该名称来源于C++,所以可以称之为虚表)。虚表的本质是一个结构体,包含了析构函数,大小,对齐和方法等信息。
在编译期,编译器只知道TraitObject包含指针的信息,并且指针的大小也是确定的(因为要在栈上分配,大小必须得是确定的),但是并不知道要调用哪个方法。在程序运行期间,当有trait_object.method()方法被调用时,TraitObject会根据虚表指针从虚表中查找出正确的函数指针,然后再进行动态调用(Java的运行时多态也是类似的)。这也是将trait对象成为动态分发的原因。
参考资料:
1.《Rust编程之道》(张汉东著P61 P71)
边栏推荐
猜你喜欢
【学术相关】陈天奇、王威廉等人推荐:ACL最佳论文奖得主给新入行研究者的一点建议...
VALDO2021——血管病变检测挑战赛之血管间隙分割(三)
Jugement des chaînes vides dans Oracle
YouTube “标签产品” 试点项目上线
第3章业务功能开发(实现显示线索主页面,并查询表单各个下拉框数据)
TCP的滑动窗口、单例模式(懒汉饿汉)双检锁/双重校验锁(DCL,即 double-checked locking)
【FreeRTOS】10 事件标志组
M using Verilog to develop GMSK modulator based on FPGA under ISE platform
HCIP第八天笔记
Chapter 3 business function development (to display the main page of clues and query the data of each drop-down box of the form)
随机推荐
十年架构五年生活-04第一个工作转折点
NepCTF2022 WP
使用修改为jmp指令的方式hook 32位函数
M carry out DS-CDMA modeling in Simulink, and then call Simulink model through MATLAB to simulate the bit error rate
Riding the wind and waves, the road of digital transformation in the era of financial technology
LeetCode 300最长递增子序列(贪心 + 二分查找比nums[i]小的第一个元素下标)、LeetCode 200岛屿数量(深搜)、LeetCode 494目标和(dfs回溯)
架构模式 节选自《闻缺陷则喜》(此书可免费下载)
Codeforces Round #809 (Div. 2) - C, D1
2022.7.20-----leetcode. one thousand two hundred and sixty
美国经济持续疲弱,微软冻结招聘:云业务和安全软件部门成重灾区
COVID-19-20——基于VNet3D分割网络的基础方法
企业电表数据采集 局域网本地存储软件系统
过时 2 天后,微软放弃“封禁”商业开源!
HCIP第十一天笔记
SparkSql中的窗口函数
MySQL中delete、Truncate、drop的区别
Database generates HTML document
[Pengcheng cup 2022] baby_ re
Judgment of empty string in Oracle
大佬们我在diea本地运行没问题,放在服务器上运行,cdc连接不上咋回事,数据库ip可以ping通