繁体   English   中英

在Rust中实际需要移动函数的情况

[英]Situations where a move to a function is actually wanted in Rust

我想确定哪些一般(或特定)情况不希望使用引用将对象传递给Rust中的函数。

我最感兴趣的是功能 (例如,一个函数是为了清理移入其中的资源),但是性能原因也很有趣(例如,如果复制一个小结构比访问它更快)通过指针)。

当然,这涉及非Copy类型。

注意:很清楚为什么在分配中使用移动语义,以防止混叠,例如,但在功能中不会出现问题。

在某些情况下,所有这些都与结构的生命周期有关,即我正在编写Octavo(加密库),其中我们有一些哈希函数(即SHA1):

let mut digest = SHA1::new();
digest.update("Ala ma kota!");

let result = digest.result(); // here we invalidate digest as it finished its work

以上情况的其他用法是构建器模式:

PizzaBuilder::new()
    .add_sauce()
    .add_cheese()
    .add_topping(Topping::Tomato)
    .add_topping(Topping::Bacon)
    .add_topping(Topping::Jalapenio)
    .bake() // here we destroy PizzaBuilder as this setup isn't usable  anymore
            // you should create new PizzaBuilder for another pizza
            // (you cannot reuse dough once you bake pizza)

考虑转换函数fn(T) -> U 如果通过引用获取T则需要在U上的所有操作来维持T的不变量。 这意味着不允许任何人以任何方式摧毁T 此外,呼叫者将负责保持输入到位以使U保持有效。 一个很好的例子是Vec::into_boxed_slice

另一个例子是移动其输入的函数。 显然,这不能接受一个&mut而没有令人担忧的语义。 一个例子是Vec::insert

另一个选择是什么时候&mut Trait: Trait 在这种情况下,使用T: Trait允许调用者决定是否使用动态调度或传递参数进行借用,这些参数具有易于使用(在两个方向上),速度和代码膨胀的分支。

另一个例子可能只是对常见情况的方便语法的偏好,其中克隆是便宜的。 一个例子可能是Vec Index<Range<usize>>

如果要限制在给定对象上调用函数的次数,还有令人信服的安全性原因。 最简单的例子是drop ,你只能调用一次。 一个非常奇特的例子是用于频道通信的“会话类型”。

移动语义的一个应用是类型安全的状态机。 假设您有一个可以处于两种状态的对象,未初始化和初始化,并且从未初始化到初始化具有副作用,并且可能会失败。 这自然地用两种类型建模,其中一种转换方法通过值接受第一种类型的对象并返回第二种类型的对象:

pub struct UninitFoo {
    ...
}

impl UninitFoo {
    pub fn new() -> UninitFoo { ... }
    pub fn configure_something(&mut self) { ... }
    pub fn configure_something else(&mut self) { ... }
    pub fn initialize(self) -> Result<InitFoo, SomeError> { ... }
}

pub struct InitFoo {
    ...
}

impl InitFoo {
    pub fn do_some_work(&mut self) { ... }
}

上面的例子真是做作,但我想你明白了。 这样,您的类型集基本上形成状态机,其中initialize()等方法是状态之间的转换。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM