Rust 如何以可变方式引用多个内容之一

Rust 如何以可变方式引用多个内容之一

问题描述

假设我想要一个可以随时在两个轨道中切换的train,并在其当前位置写入一个u8。最直接的办法可能是这样的:

struct Train<'a> {
  track_a: &'a mut [u8],
  track_b: &'a mut [u8],
  current_track: &'a mut [u8], // either track_a or track_b
  idx: usize,
}

impl<'a> Train<'a> {
  pub fn new(track_a: &'a mut [u8], track_b: &'a mut [u8]) -> Self {
    Self {
     track_a,
     track_b,
     idx: 0,
     current_track: track_a,
    }
  }

  pub fn toggle_track(&mut self) {
    if self.current_track == self.track_a {
      self.current_track = self.track_b;
    } else {
      self.current_track = self.track_a;
    }
  }

  pub fn write(&mut self, byte: u8) {
    // must be fast - can't waste time choosing track here
    self.current_track[self.idx] = byte;
    self.idx += 1;
  }
}

重要的是,我们不能浪费时间来决定当前在哪个轨道上的问题。

write。当然,上面的代码不能编译,因为我们对 track_a and track_b进行了多次可变借用。

在Rust中如何实现类似的功能呢?我尝试使用 RefCelltrack_atrack_b 进行操作,但是意识到即使是不可变 Ref也会给予对底层字节的可变访问。

难道使用unsafe Rust是实现这种数据结构的唯一方式吗?

解决方案

您可以通过以下方式来实现此功能,无需内部可变性、无需 unsafe甚至无需单独的 current_track字段:

struct Train<'a> {
    track_a: &'a mut [u8], // a.k.a, the current track
    track_b: &'a mut [u8],
    idx: usize,
}

impl<'a> Train<'a> {
    pub fn new(track_a: &'a mut [u8], track_b: &'a mut [u8]) -> Self {
        Self {
            track_a,
            track_b,
            idx: 0,
        }
    }

    pub fn toggle_track(&mut self) {
        std::mem::swap(&mut self.track_a, &mut self.track_b);
    }

    pub fn write(&mut self, byte: u8) {
        // must be fast - can't waste time choosing track here
        self.track_a[self.idx] = byte;
        self.idx += 1;
    }
}

这里的关键当然是使用std::mem::swap来通过交换两个轨道(其中一个被认为是“当前”轨道)来进行切换。唯一的缺点是,如果你需要知道最初的“第一个”和“第二个”轨道,那可能会在切换中丢失(因为这可能被认为是第一个轨道)。但是,可以通过一个单独的布尔值来完成这一点,同时保持无分支的write

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程