提问人:Kami SM 提问时间:5/29/2023 最后编辑:cafce25Kami SM 更新时间:5/29/2023 访问量:57
生存期和闭包捕获的变量如何交互?[复制]
How do lifetimes and variables captured by closures interact? [duplicate]
问:
我目前正在从《The Rust Programming Language》一书中学习 Rust,似乎我遇到了以下情况:
fn main() {
let mut s = String::from("Hello");
let mut add_suffix = || s.push_str(" world");
println!("{s}");
add_suffix();
}
导致编译器错误:
error[E0502]: cannot borrow `s` as immutable because it is also borrowed as mutable
--> src/main.rs:4:16
|
3 | let mut add_suffix = || s.push_str(" world");
| -- - first borrow occurs due to use of `s` in closure
| |
| mutable borrow occurs here
4 | println!("{s}");
| ^ immutable borrow occurs here
5 | add_suffix();
| ---------- mutable borrow later used here
|
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
我所理解的是,以某种方式对(我知道这需要可变引用)进行可变引用,从而增加了从闭包定义开始并在调用结束时结束的生存期。add_suffix
s
push_str
add_suffix
但我似乎不明白为什么在我们调用关闭之前会发生这种情况(即),为什么 Rust 会强制执行它,这有什么不安全的?如果我们想象该可变引用的生命周期在调用时开始和结束,我看不出出错的方式。add_suffix
答:
-1赞
cyqsimon
5/29/2023
#1
这与寿命无关。正如您在编译器错误中看到的那样,根本没有提到生存期。相反,这是一个“不能同时变异和别名”的简单情况。具体原因我就不多说了;TLDR 是“数据竞赛”。如果您对“为什么”感兴趣,这里有一些有用的读物:Rust 书,可变混叠问题。
在您的示例中,当闭包被定义并存储在变量中时,它已经通过可变引用捕获了。这意味着在可变引用被释放之前(也就是直到超出范围,在代码片段的第 5 行之后),不能存在其他引用(因为可变引用是排他性的)。因此,您不能在第 4 行借款。s
s
add_suffix
s
评论
0赞
Kami SM
5/30/2023
很感激,我已经进入了 Rust 的书,但我似乎不明白为什么定义闭包首先会捕获变量。
0赞
Mark Saving
6/10/2023
这与数据争用无关,数据争用只能在并发代码中发生。Rust 有引用别名规则的原因还有很多。
评论