rust - 封装可变切片修改

标签 rust

给定一个函数foo,它接受对切片的可变引用。它可以通过 a = &mut a[1..] 来减少切片的长度。但是,我一直无法弄清楚如何编写一个以相同方式改变 a 的函数。

fn foo(mut a: &mut [i32]) {

    a = &mut a[1..];

    inc(&mut a);
}

fn inc<'a: 'b, 'b>(s: &'b mut &'a mut [i32]) {
   *s = &mut s[1..];
}

inc 是编写这样一个函数的尝试。但是,它失败了:


Output of rustc nightly (Compiler #1)
error[E0623]: lifetime mismatch
 --> <source>:3:9
  |
2 | fn inc<'a: 'b, 'b>(s: &'b mut &'a mut [i32]) {
  |                       ---------------------
  |                       |
  |                       these two types are declared with different lifetimes...
3 |    *s = &mut s[1..];
  |         ^^^^^^^^^^^ ...but data from `s` flows into `s` here

最佳答案

一个更简单的错误示例是

fn oops<'a: 'b, 'b>(a: &'b mut &'a mut i32) {
    let _: &'a mut i32 = *a; // error!
}

这里的问题是,拥有 a(对某些数据的可变引用)可以让您变异(更改)它指向的值,但它不允许您移动> 值(不留下任何东西)。在 oops 中,由于一次只能对任何内容有一个可变引用,因此 *a 需要移动到 _ ,但这会使 *a 没有数据,而 a 指向“垃圾”。但无论是谁将 *a 借给 oops,都希望 *a 在归还时具有值(value),因此必须禁止这种行为。 (我说“垃圾”是因为该移动可能不会真正改变 *a ,如果我们强制执行它可能不会出错。但是如果我们不关心性能,该移动原则上可能会破坏 *a 以强制执行“一次可变借用”规则,在这种情况下你就完蛋了。)

在您的情况下, index_mut (正在实现 [1..] 语法)采用 &mut [i32] ,因此 *s 需要移至该函数。但这使得 *s 没有值,并且您不拥有 *s ,这是非法的。你最终会收回值(value)并不重要。例如。如果 index_mut 发生 panic ,调用者将期望它借给 inc 的任何变量有一个值,但不会有任何值。相反, foo 确实拥有 a ,因此可以在 a 中的 index_mut 持续时间内将 a = &mut a[1..] 保持为无值(编译器可以跟踪自有变量何时具有值和不具有值)。

一个修复(不更改界面)是在操作时将默认值粘贴到 *s 中。 impl<'a, T> Default for &'a mut[T] 提供了这个(默认值指向一个空切片),并且 std::mem::take 以安全的方式封装了 Default 实现。

fn inc<'a: 'b, 'b>(s: &'b mut &'a mut [i32]) {
   *s = &mut std::mem::take(s)[1..];
}

我同意@cdhowie的观点

fn inc<'a>(s: &'a mut [i32]) -> &'a mut [i32] {
  return s[1..];
}

并且要求 a = inc(a) 使用比 inc(&mut a) 接口(interface)更好。

关于rust - 封装可变切片修改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71551690/

相关文章:

Rust - 为什么借用 &mut 两次时它不会给我一个错误

rust - 有没有一种跨平台的方法来检查stdout是否通过管道传递到Rust中的另一个程序中?

windows - Eclipse W10 Rust 配置 "RLS"

rust - 如何从方法中修改并返回 self?

rust - 如何在Rust中使用组合器(for_each除外)在不使用while循环的情况下将流运行至完成状态?

rust - 改变循环中的两个相关值

Rust 借用检查器仅在返回具有相同生命周期的引用的函数时多次提示借用是可变的

rust - 不能在不可变切片可以使用的地方使用可变切片

rust - 如何将一个字段移出实现 Drop 特性的结构?

dictionary - 如何使用 map .or_insert_with 解决 self 借用问题?使用rust (1.11)