为什么 to_string()
会导致 borrowed value does not live long enough
错误?示例如下:
use std::collections::HashMap;
struct Foo {
id: Option<usize>,
name: String
}
fn main() {
let foos = getFoos();
for foo in foos {
let mut map = HashMap::new();
map.insert("name", &foo.name);
map.insert("id", &foo.id.unwrap().to_string());
}
}
fn getFoos() -> Vec<Foo> {
Vec::new()
}
错误:
src/main.rs:15:27: 15:54 error: borrowed value does not live long enough
src/main.rs:15 map.insert("id", &foo.id.unwrap().to_string());
^~~~~~~~~~~~~~~~~~~~~~~~~~~
src/main.rs:13:38: 16:6 note: reference must be valid for the block suffix following statement 0 at 13:37...
src/main.rs:13 let mut map = HashMap::new();
src/main.rs:14 map.insert("name", &foo.name);
src/main.rs:15 map.insert("id", &foo.id.unwrap().to_string());
src/main.rs:16 }
src/main.rs:15:9: 15:56 note: ...but borrowed value is only valid for the statement at 15:8
src/main.rs:15 map.insert("id", &foo.id.unwrap().to_string());
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/main.rs:15:9: 15:56 help: consider using a `let` binding to increase its lifetime
src/main.rs:15 map.insert("id", &foo.id.unwrap().to_string());
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
为什么编译器建议创建中间值?这个错误令人困惑 .
1 回答
您正在创建一个保存对字符串的引用的
HashMap
,即&String
. 如果我们要注释该类型,它将如下所示:这意味着 Map 包含许多对生活 somewhere else 的对象的引用 . 在你的第一个插入中,它完全正常,因为
foo.name
生活在其他地方,特别是在对象foo
中 .但是你的第二个插入有一个问题:你想引用一个生活在某个地方的
String
对象 .to_string()
创建一个由函数返回的String
,但在您的情况下,它只是一个临时对象 . 执行该行后,该对象将被销毁 .编译器是对的:
let
绑定可以解决这里的问题 .这在你的小例子中工作正常,但是当你处理更大的事情时,它可能会更复杂 . 例如,如果
HashMap
将在循环之外定义,则会出现问题,因为您插入到 Map 中的引用需要至少与 Map 本身一样长 .