当前位置:网站首页>rust中的静态分发和动态分发
rust中的静态分发和动态分发
2022-07-23 15:05: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)
边栏推荐
猜你喜欢

Transfer business append log (transaction propagation behavior)

leetcode刷题:动态规划04(不同路径)

【flask高级】从源码深入理解flask路由之endpoint
一加OnePlus 10T的一系列规格在产品发布前被披露
A series of specifications of oneplus 10t were disclosed before the product was released

乘风破浪!金融科技时代下的数字化转型之路

Redis distributed lock, it's really impossible without it

sns_ sensor_ instance_ api

【redis入门系列】redis的数据类型及相关命令

The larger the convolution kernel, the stronger the performance? An interpretation of replknet model
随机推荐
Research and implementation of network multi exit design based on policy routing deployment
xlinx pcie xvc
Interviewer: how to use redis to realize distributed locks?
Console calculator developed based on C language
基于策略路由部署的网络多出口设计研究与实现
From Markov chain to GPT, Li Hang, director of ByteDance AI Lab, detailed the past and present lives of language models
MySQL大量写入问题优化方案 MySQL参数调优
MySQL主从同步延迟解决方案
Redis数据丢失问题
phpstrom快捷键
Virtual machine network connection mode
李宏毅《机器学习》丨7. Conclusion(总结)
@Bean 注解的方法调用多次会创建多个bean 实例吗
元素内容必须由格式正确的字符数据或标记组成
Interviewer: what is the possible reason for the slow query of MySQL database besides the index problem?
LeetCode_724_寻找数组的中心下标
你真的了解Redis的持久化机制吗?
The larger the convolution kernel, the stronger the performance? An interpretation of replknet model
MySQL7种JOIN(图)
How to refine the operation of small program mall?