rust 从切片中获取可变引用

w8biq8rn  于 2023-08-05  发布在  其他
关注(0)|答案(2)|浏览(85)

我有一个特性,具有以下功能:

pub trait MappedMemory {
    fn range(&self) -> MappedMemoryRange;
    
    fn flush(&mut self);
    fn flush_range(&mut self, range: MappedMemoryRange);
    fn flush_ranges(&mut self, ranges: &[MappedMemoryRange]);
    
    fn flush_multiple(memories: &[&mut Self]);
    fn flush_multiple_ranges(memories: &[(&mut Self, MappedMemoryRange)]);
}

pub struct MappedMemoryRange {
    pub offset: u64,
    pub size: usize
}

字符串
我试图为flush_multiple提供一个调用flush_multiple_ranges的默认实现。
我尝试了这样的方法将&[&mut Self]转换为&[(&mut Self, MappedMemoryRange)]

let memories_and_ranges: Vec<(&mut Self, MappedMemoryRange)> = memories
    .into_iter()
    .map(|m| (*m, m.range()))
    .collect();


这给了我错误:

error[E0507]: cannot move out of `*m` which is behind a shared reference
  --> crates\xyz\src\objects\memory.rs:44:23
   |
44 |             .map(|m| (*m, m.range()))
   |                       ^^ move occurs because `*m` has type `&mut Self`, which does not implement the `Copy` trait


我怎样才能让rust相信我只是在沿着这些引用,就像我只有一个引用一样?

iugsix8n

iugsix8n1#

不能在不可变引用后面改变可变引用。函数签名必须是:

fn flush_multiple(memories: &mut [&mut Self])

字符串
它可以像这样实现:

let memories_and_ranges: Vec<(MappedMemoryRange, &mut Self)> = memories
    .iter_mut()
    .map(|m| (m.range(), &mut **m))
    .collect();


我交换了顺序(先MappedMemoryRange),因为在前一个顺序中,你借用m来交换m.range(),而它已经是可变借用的。
但是,我不清楚为什么不直接在每个内存上调用flush(),而不计算它的范围。

58wvjzkj

58wvjzkj2#

我的问题中有一个根本的误解,就是:&mut T并不表示可变引用,更重要的是,&T并不表示不可变引用。相反,&mut T是唯一引用,而&T是共享引用。&T仍然可以是使用内部可变性可变的。
在这个特定的例子中,我应该使用&[&Self],因为引用需要共享。只要刷新调用在返回之前释放可变内部,一切都应该是好的。而且,MappedMemory不是Sync,因此我也不需要考虑并发访问。
显然,在铁 rust 的早期有一个很大的讨论,关于mut被称为mut,而不是像uniq的东西,这是“mutpocalypse”的一部分。可悲的是,没有什么结果,因为我肯定有错误的理解了很长一段时间。

相关问题