- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在阅读一些代码,它有一个 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
反对它,会发生以下情况:
MyStruct
的指针的表。 f
的实现和 g
. &dyn MyTrait
一起存储。引用,因此引用将是其通常大小的两倍;有时&dyn
因此,引用被称为“胖引用”。 f
和 g
然后将导致使用存储在 vtable 中的指针进行间接函数调用。 MyTrait
和
MyStruct
在上一节中定义,假设您有如下函数:
fn sample<T: MyTrait>(t: T) { ... }
你通过
MyStruct
对它:
sample(MyStruct);
会发生以下情况:
sample
的副本函数是专门为 MyStruct
创建的类型。简单来说,这就像您复制并粘贴了 sample
函数定义和替换T
与 MyStruct
: 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<...>>
将导致单态性。
Vec
对于实现某种特征的外部对象,您别无选择,只能使用动态调度。例如,
Vec<Box<dyn Debug>>
.
enum
类型和单态性。
dyn
引用可能会导致更简单的代码 - 您的里程可能会有所不同。
关于rust - `dyn` 和泛型有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66575869/
我对下面的生命周期发生了什么感到困惑: struct Foo{} impl Foo { fn foo(&self, _s: &str) {} } fn main() { let foo
这个问题在这里已经有了答案: How to convert a boxed trait into a trait reference? (2 个答案) 关闭去年。 我正在尝试获取 &dyn T来自B
这个问题在这里已经有了答案: Why doesn't Rust support trait object upcasting? (4 个回答) 1年前关闭。 我有一个库需要实现特定特征( TQDisp
我有一个接收 Box 的函数并需要将其转换为 Rc在线程内共享只读所有权。 用Box一些T: Sized ,我们可以做到Rc::new(*my_box) ,但不幸的是that doesn't work
我可以接受 Box 吗?在接受 Box 的地方?如果是,如何?如果不是,为什么,还有比以下示例更优雅的方法吗? #![allow(unused)] use std::error::Error as S
这个问题在这里已经有了答案: Why doesn't Rust support trait object upcasting? (4 个回答) 2年前关闭。 如果我有 Box , 我可以返回 &dyn
我无法将参数传递给 fn。 trait T {} struct S { others: Vec>> } impl S { fn bar(&self) { for o i
在我的程序中,在辅助线程上执行了一些操作及其结果:Result>被发送回主线程。这是非常合理的错误有 Send要求,所以实际类型是Result> .我还加了 Sync能够使用 Box from方法(仅
我有一个 Vec>作为输入,我想将其元素存储在 Vec>> .最好的方法是什么? 我试过: use std::cell::RefCell; use std::rc::Rc; trait Trait {
use std::sync::Arc; pub type A = Arc Result + Send + Sync>; pub struct B { a: A, } 给 Compilin
这个问题在这里已经有了答案: Why doesn't Rust support trait object upcasting? (4 个回答) Can I cast between two trait
读完the subtyping chapter of the Nomicon ,我无法理解类型参数的协方差。特别是对于 Box类型,描述为:T is covariant . 但是,如果我写这段代码:
我尝试在 vs 包管理器中安装第三方包时反复出现此错误, Unable to resolve dependency 'openssl.v120.windesktop.msvcstl.dyn.rt-dy
我有以下简化代码。 use async_trait::async_trait; // 0.1.36 use std::error::Error; #[async_trait] trait Metric
我有以下简化的代码。 use async_trait::async_trait; // 0.1.36 use std::error::Error; #[async_trait] trait Metri
我正在尝试在线程之间共享一个函数,可以用另一个函数调用它: fn main() { let on_virtual_tun_write = std::sync::Arc::new(|f: &dy
我最近看过使用dyn关键字的代码: fn foo(arg: &dyn Display) {} fn bar() -> Box {} 这个语法是什么意思? 最佳答案 TL; DR:这是用于指定特征对象类
我正在创建HashMap>。我可以创建HashMap并插入一个实现MyTrait的结构,但是当我检索MyTrait并尝试使用它时,编译器向我提示: error[E0161]: cannot move
我正在阅读一些代码,它有一个 consume使我可以通过自己的函数 f 的函数. fn consume(self, _timestamp: Instant, len: usize, f: F) ->
我最近看到使用 dyn 关键字的代码: fn foo(arg: &dyn Display) {} fn bar() -> Box {} 这个语法是什么意思? 最佳答案 TL;DR:这是一种用于指定tr
我是一名优秀的程序员,十分优秀!