【发布时间】:2022-10-25 04:14:51
【问题描述】:
我在其他问题中没有找到答案。
我已将我的问题减少到以下几点:
use std::sync::RwLock;
pub fn main() {
iter_lock().for_each(|v| {
println!("{}", v);
});
}
fn get_lock<'a>() -> &'a RwLock<Vec<u32>> {
static mut lock: RwLock<Vec<u32>> = RwLock::new(Vec::new());
unsafe { &lock }
}
fn iter_lock<'a>() -> impl std::iter::Iterator<Item = &'a u32> {
get_lock().read().unwrap().iter()
}
上面的代码将无法编译并给出以下错误:
error[E0515]: cannot return reference to temporary value
--> src/main.rs:15:5
|
15 | get_lock().read().unwrap().iter()
| --------------------------^^^^^^^
| |
| returns a reference to data owned by the current function
| temporary value created here
|
= help: use `.collect()` to allocate the iterator
- 请注意,上面的代码中不需要静态 mut,但我需要它,因为我需要在 impl 块内定义一个变量。
- 我需要返回一个迭代器,而不是 Vec,因为我试图避免任何分配,并且该函数将始终用于迭代。
我该如何解决这个问题?我不怕使用不安全的代码,所以也欢迎不安全的建议。
【问题讨论】:
-
除了@SvenMarnach 所说的(他至少曾经在上面发表过评论!),想想你想要什么:我相信你希望你的迭代器保留
read()调用的结果,并保留RwLockReadGuard只要迭代器还活着,就活着。如果是这样,我认为这将是一个要返回的新结构,它将RwLockReadGuard移动到自身中,并充当您想要的迭代器。这不是.iter()返回的内容。 -
我对这里使用可变静态感到困惑。您的函数
get_lock()实际上是正确的,但有点奇怪。首先,使用生命周期参数'a毫无意义。您应该返回一个带有'static生命周期的引用。其次,使用可变静态是没有意义的,因为你永远不会改变它。删除mut限定符后,您就不再需要unsafe了。 (Playground) -
@KevinAnderson 啊,没想到。这很有意义
-
@SvenMarnach你是对的,这个例子中不需要静态 mut 。但在原始版本中,我确实对 RwLock 后面的数据进行了变异。不确定是使用
'a还是'static,所以谢谢你的提示! -
@Jomy 即使您在锁后面改变数据,锁本身仍然不需要是
mut。这就是重点。