rust 如何更改向量中元素的字段?

2ekbmq32  于 2022-11-12  发布在  其他
关注(0)|答案(5)|浏览(165)

我有一个结构体类型的vec,我想改变向量中第一个元素的某个字段,我该怎么做呢?
示例:

struct SomeType {
    some_value: i32,
}

fn main() {
    let mut vec = Vec::new();
    let mut t = SomeType { some_value: 45 };
    vec.push(t);

    println!("Old value: {}", vec.first().unwrap().some_value);
    vec.first().unwrap().some_value += 1;
    println!("New value: {}", vec.first().unwrap().some_value);
}

无法编译:

error: cannot assign to immutable field
  --> vec.rs:15:2
   |
15 |    vec.first().unwrap().some_value += 1;
   |    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot mutably borrow immutable field

我还不能让我的头周围的易变性的东西在 rust ;正确的方法是什么

k10s72fa

k10s72fa1#

为了改变向量的第一个元素,你通常需要一个对那个元素的引用,换句话说,一个对向量的引用,作为一个普通的结构,向量需要有一个方法来提供引用.
问题是,对向量的引用意味着你可以对向量的内部做一些事情,读取它们,或者以某种方式修改它们。Rust不知道细节,它只知道当你持有这个引用时,你可以做一些事情。
就凭这些有限的信息,Rust的借贷检查员试图阻止你搬起石头砸自己的脚。它说:如果你要读取这个向量,你可以用任何方式读取它,你甚至可以让其他函数读取它,或者两个函数,或者五个函数,但是你不能在阅读的时候修改这个向量,这是不安全的,这会导致错误,所以你可以用任意多的只读引用来读取这个向量,但只有在没有对它进行任何可写引用的情况下,才可以这样做。如果有可写引用,则一次只能有一个这样的引用。
因此,引用的类型很重要,这就是为什么向量有两种方法来给予第一个元素:第一个和第一个_mut。
所以这里

let mut vec = Vec::new();

你的向量已经是可变的了,在其他语言中,你可能会凭直觉认为,如果这个向量是可变的,那么它就永远是可变的,就像C++中的const,或者D中的immutable,它要么是可变的,要么是不可变的。
但是在Rust中,你可能希望不可变的引用进入可变的结构。例如,你可能希望一个线程处理向量的一个元素,而另一个线程处理另一个元素,如果你更愿意让借位检查器的安全带打开,那么拥有多个引用的最简单的方法就是保持它们不可变。这就是为什么像first这样的方法返回不可变引用,而要获得可变引用,需要通过使用不同的方法显式选择。
附言,那有帮助吗?
P.S.当算法需要复杂的读和写组合时,使用usizeindexes而不是引用通常很有帮助。
IndexMapusize索引也可以像这样使用。

3xiyfsfu

3xiyfsfu2#

下面是同样有效的代码示例:

vec[0].some_value += 1;

vec.first_mut().unwrap().some_value += 1;

问题中显示的代码的问题是,first()返回对第一个元素的(不可变的)引用,但需要可变引用。
索引([0])的工作方式如下:

  1. vec引用到切片
    1.在切片上建立索引从IndexMut特征调用index_mut方法
  2. index_mut方法返回可变引用(&mut someType
jv2fixgn

jv2fixgn3#

我认为您在引用时需要查找&mut


# [derive(Debug)]

struct Character{
    name: String,
}

fn main() {
    let mut hobbits = vec![
        Character{name:String::from("Sam")},
        Character{name:String::from("Merry")},
        Character{name:String::from("Pepper")},
    ];

    {
        let third = &mut hobbits[2];
        third.name = String::from("Pippin");
    }

    println!("{:?}", hobbits);
}

注意可变元素引用周围的{}。这是限制可变引用范围所必需的。不能同时具有可变和不可变引用:当third仍在作用域中时,println!将失败。

weylhg0b

weylhg0b4#

这是一个老问题,我最近刚开始研究Rust,我想尝试回答这个问题。
要更新第一个元素,我可以这样做:

let mut st = &mut vec[0];
st.some_value += 1;

或仅:

vec[0].some_value += 1;

要完全替换第一个元素,我可以这样做:

std::mem::replace(&mut vec[0], SomeType { some_value: 111 });
huwehgph

huwehgph5#

您也可以通过以下方式执行此操作:

fn changeValues(mut list: Vec<i32>){
        println!("Before value change: {:?}", list.get(0).unwrap());
        list[0] = 3;
        println!("After value change: {:?}", list.get(0).unwrap());
    }

相关问题