【问题标题】:Immutable object changing to mutable depending on function signature不可变对象根据函数签名更改为可变对象
【发布时间】:2020-06-28 12:17:38
【问题描述】:

查看下面的 Rust 代码。它编译

fn main() {
    let vec0 = Vec::new();

    let mut vec1 = fill_vec(vec0);

    println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);

    vec1.push(88);

    println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
}

fn fill_vec(mut vec: Vec<i32>) -> Vec<i32> {
    vec.push(22);
    vec.push(44);
    vec.push(66);

    vec
}

在这里,我将vec0 声明为immutable,但fill_vec 接受一个可变向量。根据函数签名,Rust 似乎正在改变所传递参数的性质。

我的问题是,这显然看起来像是“射中自己的脚”的瞬间。为什么 Rust 允许这样做?或者,这真的安全吗?我错过了什么?

【问题讨论】:

标签: rust immutability move-semantics borrow-checker


【解决方案1】:

这里有不同的事情可以解释为什么这种行为是有意义的:

  • 首先,mut 并不真的 意味着“可变”。有诸如内部可变性、Cells、Mutexes 等之类的东西,它们允许您在不需要单个 mut 的情况下修改状态。相反,mut 意味着您可以相互获得独占引用。

  • 其次,可变性是绑定的属性。 vec0 in mainvec in fill_vec 是不同的绑定,因此它们可以具有不同的可变性。

    另见:

  • 最终所有权:fill_vec 获得其参数的完全所有权,而 main 中实际上不再存在该参数。为什么不允许函数使用其拥有的参数为所欲为?如果函数将参数作为可变引用,您需要将原始绑定声明为mut

    fn main() {
        let mut vec0 = Vec::new();
        //  ^^^ now _needs_ a mutable binding
    
        fill_vec(&mut vec0);
        //       ^^^^ needs an explicit `&mut` reference
    }
    
    fn fill_vec(vec: &mut Vec<i32>) {
        //           ^^^^ borrows rather than take ownership
        // …
    }
    

【讨论】:

  • 基本术语;如果您交出某物的所有权,新所有者有权对其进行任何操作(甚至破坏),如果您有顾虑,则必须按照规则将其借给适当的目标。
  • 谢谢。这回答了我的问题。
【解决方案2】:

您正在使fill_vec 的参数vec 可变。您仍在按值传递 vec。

如果您想要一个可变引用,您可以使用vec: &amp;mut Vec&lt;i32&gt;

【讨论】:

    猜你喜欢
    • 2014-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多