Car*_*ers 6 lifetime ownership rust
我想这个问题一般都是关于生命周期的,但我特别是因为你不能写出他们的类型而对闭包有困难.
这个例子有点做作 - 我刚刚开始学习Rust,这是我一直挂着的东西.
这个程序不会编译:
fn main () {
let mut list: Vec<&Fn() -> i32> = Vec::new();
{
list.push(&|| 1);
}
}
Run Code Online (Sandbox Code Playgroud)
因为:
src/main.rs:5:25: 5:24 error: borrowed value does not live long enough
src/main.rs:5 list.push(&|| 1);
^~~~
src/main.rs:2:50: 7:2 note: reference must be valid for the block suffix following statement 0 at 2:49...
src/main.rs:2 let mut list: Vec<&Fn() -> i32> = Vec::new();
src/main.rs:3
src/main.rs:4 {
src/main.rs:5 list.push(&move || 1);
src/main.rs:6 }
src/main.rs:7 }
src/main.rs:5:9: 5:26 note: ...but borrowed value is only valid for the statement at 5:8
src/main.rs:5 list.push(&|| 1);
^~~~~~~~~~~~~~~~~
src/main.rs:5:9: 5:26 help: consider using a `let` binding to increase its lifetime
src/main.rs:5 list.push(&|| 1);
^~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
我从这个错误中收集到的是,闭包的生命周期仅限于块内的语句,但它需要为整个主体生存main.
我知道(或者,我认为)将闭包传递给push作为引用意味着push只是借用闭包,并且所有权将被返回到块.如果我可以给闭包push(即如果push取得闭包的所有权),这个代码将起作用,但由于闭包没有大小,我必须将它作为参考传递.
是对的吗?如何使此代码有效?
您要问的有两件事:
第一个问题是通过NOT指定typename来解决的,并让rust的类型推断完成工作.
let mut list: Vec<_> = Vec::new();
Run Code Online (Sandbox Code Playgroud)
第二个问题是通过不试图让关闭更长寿,但通过使其"按价值"使你可以移动它来解决.这会强制您的闭包不引用任何内容,但拥有所有捕获的值.
for i in 0..10 {
list.push(move || i);
}
Run Code Online (Sandbox Code Playgroud)
现在这给我们带来了一个新问题.如果我们添加一个不同的闭包Vec,那么类型将不匹配.因此,要实现这一点,我们需要封装封闭.
fn main () {
let mut list: Vec<Box<Fn() -> i32>> = Vec::new();
for i in 0..10 {
list.push(Box::new(move|| i));
}
{
list.push(Box::new(move|| 42));
}
}
Run Code Online (Sandbox Code Playgroud)
借用不拥有他们指向的东西.你的问题是你正在借用一个暂时的东西,它会在借来后立即停止存在,因为你没有把它存放在任何地方.如果它有帮助,考虑借用不借用值,他们借用存储,而临时只有暂时存储.
如果您希望在任何给定时间内借入某些东西,您必须从至少持续这么长时间的存储中借用.在这种情况下,因为要存储在借Vec,这意味着,无论您的存储从借用必须活得比的Vec还有.从而:
fn main () {
let closure;
let mut list: Vec<&Fn() -> i32> = Vec::new();
{
closure = || 1;
list.push(&closure);
}
}
Run Code Online (Sandbox Code Playgroud)
注意之前closure定义的是.在Rust中,值在其作用域的末尾以反向词法顺序删除,因此之后定义的任何变量必然会在它之前被删除,从而导致包含无效指针. list listlist
如果要推送多个闭包,则每个闭包需要一个单独的变量.
为了预防一个可能的"我的实际问题不是这个简单的"附录(:P):如果你需要返回list或以某种方式坚持它超出单个函数调用,请注意,没有办法扩展借用.在这种情况下,您需要做的是更改list为拥有的盒装闭包(即 Vec<Box<Fn() -> i32>>)的向量.
| 归档时间: |
|
| 查看次数: |
330 次 |
| 最近记录: |