如何从方法中更改结构体的字段?

How I can mutate a struct's field from a method?

提问人:alxkolm 提问时间:11/20/2014 最后编辑:Shepmasteralxkolm 更新时间:1/7/2020 访问量:97003

问:

我想这样做:

struct Point {
    x: i32,
    y: i32,
}

impl Point {
    fn up(&self) {
        self.y += 1;
    }
}

fn main() {
    let p = Point { x: 0, y: 0 };
    p.up();
}

但是这段代码会抛出一个编译器错误:

error[E0594]: cannot assign to field `self.y` of immutable binding
 --> src/main.rs:8:9
  |
7 |     fn up(&self) {
  |           ----- use `&mut self` here to make mutable
8 |         self.y += 1;
  |         ^^^^^^^^^^^ cannot mutably borrow field of immutable binding
可变

评论


答:

188赞 Vladimir Matveev 11/20/2014 #1

您需要使用 instead of 并使变量可变:&mut self&selfp

struct Point {
    x: i32,
    y: i32,
}

impl Point {
    fn up(&mut self) {
        // ^^^ Here
        self.y += 1;
    }
}

fn main() {
    let mut p = Point { x: 0, y: 0 };
    //  ^^^ And here
    p.up();
}

在 Rust 中,可变性是继承的:数据的所有者决定值是否可变。然而,引用并不意味着所有权,因此它们本身可以是不可变的,也可以是可变的。您应该阅读解释所有这些基本概念的官方书籍

评论

80赞 Aeolun 8/18/2017
@VladimirMatveev我只想说,即使你读过并通读了这本书,以前从未见过这些概念,在你遇到相关的实际情况之前,它可能没有多大意义。就像对我来说一样,所以这些答案仍然非常有帮助;)
15赞 Syndog 10/8/2018
@Aeolun - 说得好。我读了这本书,以为我理解了这个概念,但发现我真的没有,直到我开始做一个真正的 Rust 项目。
2赞 dawid 3/15/2021
这本书并不完美。
19赞 silvioprog 1/7/2020 #2

通过使用 可以模拟字段级可变性:Cell<T>

use std::cell::Cell;

struct Point {
    x: i32,
    y: Cell<i32>,
}

impl Point {
    fn up(&self) {
        self.y.set(self.y.get() + 1);
    }
}

fn main() {
    let p = Point { x: 0, y: Cell::new(0) };
    p.up();
    println!("y: {:?}", p.y);
}

这将打印出来,并且我们已经成功更新了。y: Cell { value: 7 }y

此外,如果使用的是 channel,则可以在文件顶部声明并在方法中使用以下语法:nightly#![feature(cell_update)].rsup()

impl Point {
    fn up(&self) {
        self.y.update(|x| x + 1);
    }
}

注意:上述此功能是仅限每晚的实验性 API。

摘自 Rust 1.7 的 Rust 编程语言

评论

0赞 mallwright 1/13/2020
这同样适用于 Box、Rc、Arc 吗?
0赞 silvioprog 1/17/2020
是的,确实如此。您可以将它们组合在一起,例如:... .Rc<Cell<i32>>y: Rc::new(Cell::new(0)),