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

Phi*_*wig 6 rust

我有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);
}
Run Code Online (Sandbox Code Playgroud)

这无法编译:

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

我无法理解Rust中的可变性东西; 这里有什么正确的方法?

dmi*_*_vk 9

这是同样有效的代码示例:

vec[0].some_value += 1;

vec.first_mut().unwrap().some_value += 1;
Run Code Online (Sandbox Code Playgroud)

所显示代码的问题是first()返回对第一个元素的(不可变)引用,但需要可变引用。

索引 ( [0]) 的工作方式如下:

  1. vec 取消对切片的引用
  2. index_mutIndexMut特征索引切片调用方法
  3. index_mut方法返回可变引用 ( &mut someType)


Art*_*mGr 6

要改变向量的第一个元素,通常会得到对该元素的引用.换句话说,参考载体中.作为一个普通的结构,向量需要有一个方法来为你提供参考.

事实上,对向量的引用意味着你可以对向量的内部做一些事情,读取它们或以某种方式修改它们.Rust不知道细节,它只知道你拿着那个引用时,你可以做些什么.

只有那些有限的信息,Rust的借用检查器试图阻止你在脚下射击自己.它说:如果你要读取矢量,那么你可以按照你想要的任何方式读取它,你甚至可以读一些其他功能,或者两个函数,或者五个.但是你在阅读它时不能修改矢量,它不安全,它会导致错误.因此,您可以根据需要在向量中包含尽可能多的只读引用,但仅限于当您没有持有任何可写引用时.如果您确实持有可写参考,那么一次只能有一个这样的参考.

因此这种参考很重要.这就是为什么向量有两个方法可以为你提供第一个元素:firstfirst_mut.

所以在这里

let mut vec = Vec::new();
Run Code Online (Sandbox Code Playgroud)

你的载体已经变异了.来自其他语言的你可能会从直觉中发挥作用,即如果向量是可变的一次,它总是可变的.有点像constC++或immutableD中的价值.它可能是可变的,也可能不是.

但在Rust中,您可能希望将不可变引用转换为可变结构.例如,您可能希望一个线程处理向量的一个元素而另一个元素处理另一个元素,如果您宁愿保持借用检查器的安全带,那么拥有多个引用的最简单方法是使它们保持不变.这就是为什么首先返回不可变引用和获取可变引用的方法需要通过使用不同的方法显式选择.

PS那么有什么帮助吗?


Shc*_*ova 5

我认为您在&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);
}
Run Code Online (Sandbox Code Playgroud)

注意{}可变元素引用。需要限制可变引用范围。不能同时拥有可变和不可变引用:println!third仍在范围内时会失败。


You*_*hah 5

这是一个老问题了。我最近开始接触 Rust,我想尝试回答一下。

要更新第一个元素,我会这样做:

let mut st = &mut vec[0];
st.some_value += 1;
Run Code Online (Sandbox Code Playgroud)

要不就:

vec[0].some_value += 1;
Run Code Online (Sandbox Code Playgroud)

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

std::mem::replace(&mut vec[0], SomeType { some_value: 111 });
Run Code Online (Sandbox Code Playgroud)