gpt4 book ai didi

rust - `dyn` 和泛型有什么区别?

转载 作者:行者123 更新时间:2023-12-03 11:25:48 26 4
gpt4 key购买 nike

我正在阅读一些代码,它有一个 consume使我可以通过自己的函数 f 的函数.

fn consume<R, F>(self, _timestamp: Instant, len: usize, f: F) -> Result<R>
where
F: FnOnce(&mut [u8]) -> Result<R>,
我写了一些类似的代码,但是像这样:
pub fn phy_receive(
&mut self,
f: &mut dyn FnMut(&[u8])
) -> u8 {
公平地说,我不知道有什么区别,除了 FnOnce对比 FnMut .使用 dyn 有什么区别? vs 一个泛型类型参数来指定这个函数?

最佳答案

使用 dyn with types 会导致动态调度(因此是 dyn 关键字),而使用(受约束的)泛型参数会导致单态性。
一般说明
动态调度
动态分派(dispatch)意味着方法调用在运行时被解析。就运行时资源而言,它通常比单态更昂贵。
例如,假设您具有以下特征

trait MyTrait {
fn f(&self);
fn g(&self);
}
和一个结构 MyStruct它实现了该特征。如果您使用 dyn引用该特征(例如 &dyn MyTrait ),并将引用传递给 MyStruct反对它,会发生以下情况:
  • 创建了一个“vtable”数据结构。这是一个包含指向 MyStruct 的指针的表。 f 的实现和 g .
  • 指向此 vtable 的指针与 &dyn MyTrait 一起存储。引用,因此引用将是其通常大小的两倍;有时&dyn因此,引用被称为“胖引用”。
  • 调用fg然后将导致使用存储在 vtable 中的指针进行间接函数调用。

  • 单态
    单态意味着代码是在编译时生成的。它类似于复制和粘贴。使用 MyTraitMyStruct在上一节中定义,假设您有如下函数:
    fn sample<T: MyTrait>(t: T) { ... }
    你通过 MyStruct对它:
    sample(MyStruct);
    会发生以下情况:
  • 在编译期间,sample 的副本函数是专门为 MyStruct 创建的类型。简单来说,这就像您复制并粘贴了 sample函数定义和替换TMyStruct :
  • fn sample__MyStruct(t: MyStruct) { ... }
  • sample(MyStruct) call 被编译成 sample__MyStruct(MyStruct) .

  • 这意味着一般而言,单态在二进制代码大小方面可能会更昂贵(因为您实际上是在复制相似的代码块,但针对不同的类型),但是没有像动态调度那样的运行时成本。
    你的例子
    由于 FnMut只是一个特征,上述讨论直接适用于您的问题。这是特征定义:
    pub trait FnMut<Args>: FnOnce<Args> {
    pub extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
    }
    忽略 extern "rust-call"奇怪,这是一个特征,就像 MyTrait多于。这个特性是由某些 Rust 函数实现的,所以这些函数中的任何一个都类似于 MyStruct从上面。使用 &dyn FnMut<...>将导致动态调度,并使用 <T: FnMut<...>>将导致单态性。
    我的 2 美分和一般建议
    某些情况会要求您使用动态调度。例如,如果您有 Vec对于实现某种特征的外部对象,您别无选择,只能使用动态调度。例如, Vec<Box<dyn Debug>> .
    但是,如果这些对象在您的代码内部,您可以使用 enum类型和单态性。
    除此之外,在所有条件相同的情况下,我的建议是尽可能使用单态,如果必须,使用动态调度。就个人而言,我注意到在我的大部分代码中,我最终只调用了一次或两次该函数。如果您只调用一次,您将免费获得单态,因为二进制代码只会生成一次。另一方面,使用 dyn引用可能会导致更简单的代码 - 您的里程可能会有所不同。

    关于rust - `dyn` 和泛型有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66575869/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com