在 Rust 中,闭包中的 Send 和 'static 有什么区别?

3

考虑以下结构体:

struct Promise1<T, Err> {
    on_resolve:Option<|promised:T|: Send>,
    on_reject:Option<|failed:Err|: Send>,
}

struct Promise2<T, Err> {
    on_resolve:Option<|promised:T|: 'static>,
    on_reject:Option<|failed:Err|: 'static>,
}

struct Promise3<'a, T, Err> {
    on_resolve:Option<|promised:T|: 'a>,
    on_reject:Option<|failed:Err|: 'a>,
}

它们之间具体有什么区别?

'Send'作为绑定时,为什么当提供'Send'时就不再需要提供生命周期?这个隐含的生命周期是由'Send'生成的吗?

具体来说,'Send'和闭包边界中的'static'有什么区别。

例如,以下代码可以工作:

let k:|int|:Send = |i:int| {};
let p:|int|:Send = |i:int| {};
Promise1 {
    on_resolve:Some(k),
    on_reject:Some(p)
};

但这并不包括:
let k = |i:int| {};
let p = |i:int| {};
Promise1 {
    on_resolve:Some(k),
    on_reject:Some(p)
};

错误:

error: mismatched types: expected `core::option::Option<'static |_|:Send>`, found 
`core::option::Option<|int|>` (expected bounds `Send`, found no bounds)

然而,使用 Promise2 或 Promise3 与 'static 和 'a 相应地一起使用时,这个问题可以很好地解决。

2个回答

3

Send 是一个“种类” http://doc.rust-lang.org/reference.html#built-in-traits

send : 能够跨任务边界发送。

'static 是一种特殊的生命周期:持续整个程序的生命周期。

参考文献还包含了关于 Send 的另一个启示性部分:(我们尚未获得参考文献的最佳布局)http://doc.rust-lang.org/reference.html#type-kinds

Send:此类类型可以在任务之间安全地发送。此类包括标量、盒子、进程和仅包含其他拥有类型的结构类型。所有 Send 类型都是 'static。

这就是为什么您可以在某些情况下交替使用它们的原因。


2
为什么我们要谈论终身?闭包嵌入一个环境,该环境可能包含或不包含对当前线程堆栈的引用。此环境具有生命周期限制,指示其可行的最长时间,并对应于任何嵌入引用的最短生命周期,您可以使用适当的符号表示。如果它包含对当前线程堆栈的引用,则闭包的生命周期不应超过所述引用的生命周期。如果它包含对静态资源的引用,并且未与线程堆栈链接,则闭包的生命周期不受限制。'static是上限,因为它不给出任何限制,因此'static用于指示没有任何生命周期约束的情况。它避免了特殊情况:始终存在生命周期限制,只是有时“无限”。
“Send”是一种应用于对象的类型,以指示它可以安全地发送到另一个线程,例如通过通道。因此,它意味着该对象不包含对当前线程堆栈的引用,否则,如果堆栈展开,则对象将包含悬空引用!
为什么“Send”似乎意味着“静态”?
- 如果一个对象没有引用到当前堆栈,它的生命周期边界就是“静态”。 - “Send”意味着一个对象没有引用到当前堆栈。 因此,“Send”暗示了对象的生命周期边界是“静态”。
但是,实际上有安全的方法来引用另一个堆栈的引用,例如在fork-join并行性中,在这种情况下,被引用的线程确保其超出借用引用的线程的生命周期。它在这里进行了简要介绍,并且似乎需要不同的类型来精确指定如何安全地共享数据。

你能解释一下 'static 在所有权模型和释放内存方面的工作原理吗?我很难理解将具有静态生命周期声明的参数传递到函数中意味着什么。传入的项目是否必须在程序的整个生命周期内存在?这是一种内存泄漏吗? - jocull
经过一些实验,我认为我明白了... http://is.gd/8KWutk 'static 表示给定的 Trait 是静态的 -- 而不是传递进来的项目!这更有意义。 - jocull
@jocull: 'static 的意思是“程序的生命周期”。(1)&'static T 表示 T 的实例必须与程序一样长寿,可以通过泄漏它(呃...)或者只是因为它是一个 static 常量来实现。(2) Trait + 'static 表示该项不应包含寿命小于 'static 的引用,可以通过仅包含 &'static T 或不包含任何引用来实现。 - Matthieu M.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接