【问题标题】:How to swap two fields of a struct如何交换结构的两个字段
【发布时间】:2016-02-26 11:00:07
【问题描述】:

我已经开始学习 Rust,并且正在尝试实现一个简单的一维元胞自动机。我想将自动机状态(Board)表示为包含大小和两个不同向量(大小相同)的结构。我试过了:

struct Board {
    n: usize,
    cur:  Vec<u32>,
    next: Vec<u32>,
}

impl Board {
    fn new(size: usize) -> Board {
        Board {
            n: size,
            cur: vec![0;size],
            next: vec![0;size],
        }
    }
}

到目前为止一切顺利。我也能够改变这两个向量。但后来我希望能够交换两个向量(或者更确切地说是它们的引用),例如:

fn swap(&mut self) -> &Board {
    let tmp = self.cur;
    self.cur = self.next;
    self.next = tmp;
    self
}

它失败了,我想我可以理解cannot move out of borrowed content [E0507]。我还尝试了mem::swap,我在一个类似标题的问题中找到了它,但没有成功。

我怎样才能使这个例子工作? (由于我是 Rust 的初学者,请毫不犹豫地提出不同的数据表示)。

【问题讨论】:

    标签: struct reference rust swap


    【解决方案1】:

    有什么问题?

    您正在在数据中打孔

    fn swap(&mut self) -> &Board {
        let tmp = self.cur;         // 1
        self.cur = self.next;       // 2
        self.next = tmp;            // 3
        self
    }
    

    如果我们逐行分析:

    1. self.cur 现在未初始化
    2. self.next 现在未初始化
    3. 一切都再次洁净

    如果在第 (3) 行发生变化以收紧情况之前由于某种原因计算中断,self 现在已中毒,可能会导致各种令人讨厌的事情发生。值得注意的是,它的析构函数可能会尝试两次释放内存。

    理论上,您可以让编译器检查临时漏洞并毫无疑问地证明:

    • 打孔时没有函数访问self
    • 在范围结束时,无论是正常到达还是通过展开,孔都会再次被填满

    确实在某些时候它被考虑过......但事实是它很复杂并且有现成的解决方法。

    那么?

    答案在于std::mem,它公开了以安全方式执行此类低级操作的函数。虽然函数本身是在底层使用 unsafe 实现的,但它们依靠对语言和运行时的理解来公开安全接口。

    您会感兴趣的两个特定功能是:

    • replace:将dest: &amp;mut T 的内容替换为src: T,并返回之前包含在dest 后面的内容
    • swap:交换其参数的内容

    使用这两个简单而安全的原语,您可以避免在数据中打孔。

    【讨论】:

      【解决方案2】:

      如您所见,mem::swap 是正确的选择:

      fn swap(&mut self) -> &Board {
          std::mem::swap(&mut self.cur, &mut self.next);
          self
      }
      

      这行得通。请注意,当使用 . 时,您将取消对 self 的引用。所以虽然self 的类型为&amp;mut Boardself.cur 的类型为Vec&lt;u32&gt;。因此编译器抱怨“移出借来的内容”,我们需要额外的&amp;muts。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-12
        • 2022-07-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多