struct - 如何交换结构的两个字段

标签 struct reference rust swap

我已经开始学习 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 的初学者,请毫不犹豫地提出不同的数据表示法)。

最佳答案

What's the problem?

您正在打洞您的数据:

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
  • 到作用域的末尾,无论是正常到达还是展开,孔都被再次填满

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

So?

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

您会感兴趣的两个特定函数是:

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

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

关于struct - 如何交换结构的两个字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35649968/

相关文章:

c - 在 C 中打印结构体的名称

random - 无法创建向量并将其打乱

rust - 为什么返回 Result 的函数总是返回 Err?

C++98 如何在 header 中初始化静态结构数组

struct - Julia:我们可以对不可变结构类型中的对象进行多少更改?

Java 引用不正确

c++ - 通过引用传递类对象

c++ - 函数 + 引用变量 - 编程作业 - C++

rust - 将Vec <u64>转换为Vec <(&str,u64)>以获取tui::BarChart数据

c - 形式论证中如何修改结构变量