使用 HashMap 引用作为值的 HashMap 的生命周期问题
Lifetime problem with HashMap with HashMap references as values
(生锈新手,仅供参考!)
所以 - 我一直在努力理解 Rust 中生命周期的概念。我已经阅读了文档,并阅读了一些关于该主题的博客和 SO posts。但仍然完全明白(因此,问题的标题可能不好)。
我有一个特别的问题想弄清楚,我已经将其归结为这个小示例代码(试图尽可能接近工作示例):
use std::collections::HashMap;
// Imagine this is actually a more complex type:
type BigComplexType = i32;
fn some_expensive_computation() -> BigComplexType {
// Imagine this takes some arguments, and takes a long time to run
return 123;
}
fn construct() -> HashMap<i32, &'static HashMap<i32, BigComplexType>> {
let mut main = HashMap::new();
let mut nested = HashMap::new();
nested.insert(1111, some_expensive_computation());
nested.insert(2222, some_expensive_computation());
// ... and lots more inserts...
main.insert(10, &nested);
main.insert(20, &nested);
// ... and lots more inserts...
// Imagine a lot more other nested HashMaps to follow here
// let mut nested2 = ...
// ...
// main.insert(..., &nested2);
// ...
return main;
}
fn main() {
construct();
}
这个例子有点琐碎 - 在实际代码中,我在 construct()
函数中创建了更复杂、更深入的结构。
我想做的是创建某种缓存来保存这些 pre-computed 值,以便可以在代码中的其他地方轻松快速地访问它们。也许这一切都可以通过一些完全不同的方式来完成 - 但我认为必须有一种方法可以做到这一点。
但是,rustc
这里就报错了,因为nested
只存在于construct()
,一旦我们脱离了这个函数,它就不存在了,所以所有的引用都是无效(或者,这就是我对问题的理解)。
我尝试将 'a
生命周期引入 construct()
函数,并在下面的 nested
HashMap 上使用该生命周期,但没有骰子。出现了一些错误,并且永远无法完全使其正常工作。我已经尝试了各种添加生命周期注释的变体,但没有成功。
我有一种感觉,我只是没有理解这里整个概念的某些方面。谁能帮我指明正确的方向?
(我确实考虑过将 nested
HashMap 收集到一个向量中并与 main
hashmap 一起返回 - 这样函数就会返回主 HashMap,加上嵌套的向量那些 - 因此,生命周期将得到保证,我 认为 - 但我尝试这样做时遇到了其他一些障碍,并且感觉我是 over-complicating 东西。)
供参考,这是我在编译上面得到的错误:
error[E0515]: cannot return value referencing local variable `nested`
--> lifetime_return.rs:29:12
|
19 | main.insert(10, &nested);
| ------- `nested` is borrowed here
...
29 | return main;
| ^^^^ returns a value referencing data owned by the current function
error[E0515]: cannot return value referencing local variable `nested`
--> lifetime_return.rs:29:12
|
20 | main.insert(20, &nested);
| ------- `nested` is borrowed here
...
29 | return main;
| ^^^^ returns a value referencing data owned by the current function
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0515`.
Any/all 帮助将不胜感激!我试图寻找类似的问题,但找不到一个 - 也许我只是没有将某些 SO post 识别为重复项,因为我还没有完全理解生命周期模型。
你对为什么这不起作用的直觉是正确的:nested
只存在于 construct
中,你尝试 return 在 hashmap 中对它的引用更长时间比功能。假设您不想克隆嵌套地图,大概是因为它们非常大,您可以使用 Rc
作为一种方式来对嵌套地图进行简单的可克隆引用,使它们在必要的:
use std::collections::HashMap;
use std::rc::Rc;
type BigComplexType = i32;
fn some_expensive_computation() -> BigComplexType {
return 123;
}
fn construct() -> HashMap<i32, Rc<HashMap<i32, BigComplexType>>> {
let mut main = HashMap::new();
let mut nested = HashMap::new();
nested.insert(1111, some_expensive_computation());
nested.insert(2222, some_expensive_computation());
let nested_rc = Rc::new(nested);
main.insert(10, Rc::clone(&nested_rc));
main.insert(20, nested_rc); // can move the Rc for the last insert
let mut nested2 = HashMap::new();
nested2.insert(3333, some_expensive_computation());
nested2.insert(4444, some_expensive_computation());
let nested2_rc = Rc::new(nested2);
main.insert(30, Rc::clone(&nested2_rc));
main.insert(40, nested2_rc);
return main;
}
fn main() {
let map = construct();
println!("{}", map[&10][&1111]); // 123
}
(生锈新手,仅供参考!)
所以 - 我一直在努力理解 Rust 中生命周期的概念。我已经阅读了文档,并阅读了一些关于该主题的博客和 SO posts。但仍然完全明白(因此,问题的标题可能不好)。
我有一个特别的问题想弄清楚,我已经将其归结为这个小示例代码(试图尽可能接近工作示例):
use std::collections::HashMap;
// Imagine this is actually a more complex type:
type BigComplexType = i32;
fn some_expensive_computation() -> BigComplexType {
// Imagine this takes some arguments, and takes a long time to run
return 123;
}
fn construct() -> HashMap<i32, &'static HashMap<i32, BigComplexType>> {
let mut main = HashMap::new();
let mut nested = HashMap::new();
nested.insert(1111, some_expensive_computation());
nested.insert(2222, some_expensive_computation());
// ... and lots more inserts...
main.insert(10, &nested);
main.insert(20, &nested);
// ... and lots more inserts...
// Imagine a lot more other nested HashMaps to follow here
// let mut nested2 = ...
// ...
// main.insert(..., &nested2);
// ...
return main;
}
fn main() {
construct();
}
这个例子有点琐碎 - 在实际代码中,我在 construct()
函数中创建了更复杂、更深入的结构。
我想做的是创建某种缓存来保存这些 pre-computed 值,以便可以在代码中的其他地方轻松快速地访问它们。也许这一切都可以通过一些完全不同的方式来完成 - 但我认为必须有一种方法可以做到这一点。
但是,rustc
这里就报错了,因为nested
只存在于construct()
,一旦我们脱离了这个函数,它就不存在了,所以所有的引用都是无效(或者,这就是我对问题的理解)。
我尝试将 'a
生命周期引入 construct()
函数,并在下面的 nested
HashMap 上使用该生命周期,但没有骰子。出现了一些错误,并且永远无法完全使其正常工作。我已经尝试了各种添加生命周期注释的变体,但没有成功。
我有一种感觉,我只是没有理解这里整个概念的某些方面。谁能帮我指明正确的方向?
(我确实考虑过将 nested
HashMap 收集到一个向量中并与 main
hashmap 一起返回 - 这样函数就会返回主 HashMap,加上嵌套的向量那些 - 因此,生命周期将得到保证,我 认为 - 但我尝试这样做时遇到了其他一些障碍,并且感觉我是 over-complicating 东西。)
供参考,这是我在编译上面得到的错误:
error[E0515]: cannot return value referencing local variable `nested`
--> lifetime_return.rs:29:12
|
19 | main.insert(10, &nested);
| ------- `nested` is borrowed here
...
29 | return main;
| ^^^^ returns a value referencing data owned by the current function
error[E0515]: cannot return value referencing local variable `nested`
--> lifetime_return.rs:29:12
|
20 | main.insert(20, &nested);
| ------- `nested` is borrowed here
...
29 | return main;
| ^^^^ returns a value referencing data owned by the current function
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0515`.
Any/all 帮助将不胜感激!我试图寻找类似的问题,但找不到一个 - 也许我只是没有将某些 SO post 识别为重复项,因为我还没有完全理解生命周期模型。
你对为什么这不起作用的直觉是正确的:nested
只存在于 construct
中,你尝试 return 在 hashmap 中对它的引用更长时间比功能。假设您不想克隆嵌套地图,大概是因为它们非常大,您可以使用 Rc
作为一种方式来对嵌套地图进行简单的可克隆引用,使它们在必要的:
use std::collections::HashMap;
use std::rc::Rc;
type BigComplexType = i32;
fn some_expensive_computation() -> BigComplexType {
return 123;
}
fn construct() -> HashMap<i32, Rc<HashMap<i32, BigComplexType>>> {
let mut main = HashMap::new();
let mut nested = HashMap::new();
nested.insert(1111, some_expensive_computation());
nested.insert(2222, some_expensive_computation());
let nested_rc = Rc::new(nested);
main.insert(10, Rc::clone(&nested_rc));
main.insert(20, nested_rc); // can move the Rc for the last insert
let mut nested2 = HashMap::new();
nested2.insert(3333, some_expensive_computation());
nested2.insert(4444, some_expensive_computation());
let nested2_rc = Rc::new(nested2);
main.insert(30, Rc::clone(&nested2_rc));
main.insert(40, nested2_rc);
return main;
}
fn main() {
let map = construct();
println!("{}", map[&10][&1111]); // 123
}