所以我有一个长这样的函数
fn foo() {
let items = vec![0.2, 1.5, 0.22, 0.8, 0.7, 2.1];
let mut groups: HashMap<u32, String> = HashMap::new();
let mut group = |idx: f32| -> &mut String {
let rounded = (idx / 0.2).floor() as u32;
groups
.entry(rounded)
.or_insert_with(|| format!("{}:", rounded))
};
for item in items.iter() {
group(*item).push_str(&format!(" {}", item))
}
}
这段代码无法编译,会出现以下错误:
error: captured variable cannot escape `FnMut` closure body
--> src/main.rs:9:9
|
5 | let mut groups: HashMap<u32, String> = HashMap::new();
| ---------- variable defined here
6 |
7 | let mut group = |idx: f32| -> &mut String {
| - inferred to be a `FnMut` closure
8 | let rounded = (idx / 0.2).floor() as u32;
9 | groups
| ^-----
| |
| _________variable captured here
| |
10 | | .entry(rounded)
11 | | .or_insert_with(|| format!("{}:", rounded))
| |_______________________________________________________^ returns a reference to a captured variable which escapes the closure body
|
= note: `FnMut` closures only have access to their captured variables while they are executing...
= note: ...therefore, they cannot allow references to captured variables to escape
编辑
正如 @Sven Marnach 指出的那样,问题在于我可以创建指向同一对象的 2 个可变引用:
fn foo() {
// ...
let ok = groups(0.1);
let problem = groups(0.1);
}
Translated (corrected)
I think that Rust is warning me that the closure
group
is mutably capturing the variablegroups
and then returning a reference to an object owned bygroups
. The risk here is that the following code would return a dangling pointer (sincegroups
is dropped when it goes out of scope afterfoo
finishes).fn foo() -> &String { /* ... */ return groups(0.1); }
Is there a way to return a reference from a captured mutable HashMap
like this?
foo()
返回引用。问题在于你可能第二次调用group()
并最终得到两个可变引用指向同一个值。正如错误信息所述 -FnMut
闭包不能返回对其捕获值的任何引用。 - Sven Marnach