我如何从方法中改变结构的字段?

alx*_*olm 52 mutable rust

我想做这个:

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

但是这段代码抛出了编译器错误:

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
Run Code Online (Sandbox Code Playgroud)

Vla*_*eev 77

您需要使用&mut self而不是&self使p变量变为可变:

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

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

  • @VladimirMatveev我只是想说,即使你阅读并完成了本书,从未见过这些概念,在你遇到相关的实际情况之前可能没有多大意义.对我来说,所以这些答案仍然非常有用;) (20认同)
  • @Aeolun-说得很好。我浏览了《书》,以为自己理解了这个概念,但是发现直到开始从事实际的Rust项目时,我才真正意识到这一点。 (3认同)
  • 这本书并不完美。 (2认同)

sil*_*rog 5

By using Cell<T> you can emulate field-level mutability:

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

This will print y: Cell { value: 7 } and we've successfully updated y.

Additionally, if you are using nightly channel, you can declare #![feature(cell_update)] on top of your .rs file and use the following syntax inside your up() method:

impl Point {
    fn up(&self) {
        self.y.update(|x| x + 1);
    }
}
Run Code Online (Sandbox Code Playgroud)

Note: This feature above is a nightly-only experimental API.

From The Rust Programming Language at Rust 1.7.