此问题在此处已有答案:
Why can't I store a value and a reference to that value in the same struct?(4个答案)
上个月关门了。
如何摆脱下面的生命周期错误,其中我设置了一个Option引用成员变量来引用本地函数堆栈变量。
use std::collections::HashMap;
use std::sync::mpsc;
struct Mt<'a> {
list: HashMap<u32, Data>,
to_be_processed_data_ref: Option<&'a Data>,
hash_map_data_ref: Option<&'a Data>,
rx: mpsc::Receiver<Data>,
}
impl <'a> Mt<'a> {
fn new(rx: mpsc::Receiver<Data>) -> Self {
Mt {
list: HashMap::new(),
to_be_processed_data_ref: None,
hash_map_data_ref: None,
rx,
}
}
fn add_to_hash_map(&mut self, k: u32, data: Data) {
self.list.insert(k, data);
}
fn check(&mut self) {
let data = self.rx.recv().unwrap();
// make use of self.hash_map_data_ref and self.to_be_processed_data_ref in other Mt member functions and set them to None at the end
self.to_be_processed_data_ref = Some(&data);
for (_, val) in &self.list {
self.hash_map_data_ref = Some(val);
self.test1();
self.test2();
self.test3();
}
self.hash_map_data_ref = None;
self.to_be_processed_data_ref = None;
}
fn test1(&self) {
// access self.hash_map_data_ref and self.to_be_processed_data_ref
}
fn test2(&self) {
// access self.hash_map_data_ref and self.to_be_processed_data_ref
}
fn test3(&self) {
// access self.hash_map_data_ref and self.to_be_processed_data_ref
}
}
struct Data {
x: f32,
y: f32,
}
impl Data {
fn new(x: f32, y: f32) -> Self {
Data {
x,
y,
}
}
}
fn main() {
// Create a simple streaming channel
let (tx, rx) = mpsc::channel::<Data>();
let mut mt = Mt::new(rx);
mt.add_to_hash_map(1, Data::new(10.0f32, 20.0f32));
mt.add_to_hash_map(2, Data::new(100.0f32, 200.0f32));
mt.add_to_hash_map(3, Data::new(1000.0f32, 2000.0f32));
mt.add_to_hash_map(4, Data::new(10000.0f32, 20000.0f32));
mt.add_to_hash_map(5, Data::new(100000.0f32, 200000.0f32));
tx.send(Data::new(1.0f32, 2.0f32));
mt.check();
}
字符串
1条答案
按热度按时间hjzp0vay1#
不幸的是,这里存在一个关于生存期的基本问题,最好的办法是重构
test1
、test2
和test3
,以简单地引用data
和hash_map_data_ref
。从表面上看,以下模式:
字符串
would seem to be valid -在
data
被删除或移动之前删除引用。然而,这里有两个问题:Mt<'a>
中的Option<&'a Data>
字段要求您在字段中放置的任何引用都必须引用一个与'a
一样长的对象,即使您承诺足够快地清除引用,这并不满足关于self
和'a
存活时间与data
存活时间的静态检查。test
函数panic并且panic被捕获,则此代码实际上是不可靠的。通常,捕获的panic可能导致 * 破坏的不变量 *,但这种模式不应导致不可靠。然而,在这种情况下,panic将允许调用者观察到一个悬空引用:
data
在panic解除时被丢弃,但引用仍然存在。Here是一个交互式演示,显示了遇到悬空引用时程序中断。为了回答的完整性,我将在底部包含一个代码副本。确切的结构取决于你需要对列表和Map引用做什么,我不能准确地弄清楚。然而,这里有一个框架应该可以工作:
型
注意,你不能在
test1
或test2
中改变self.list
,因为在列表上的迭代已经从它借用了。我想给定test1(&self)
的签名,这对你来说应该不是问题。不健全证明:
型