提问人:alxkolm 提问时间:11/20/2014 最后编辑:Shepmasteralxkolm 更新时间:1/7/2020 访问量:97003
如何从方法中更改结构体的字段?
How I can mutate a struct's field from a method?
问:
我想这样做:
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
&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();
}
在 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)]
.rs
up()
impl Point {
fn up(&self) {
self.y.update(|x| x + 1);
}
}
注意:上述此功能是仅限每晚的实验性 API。
评论
0赞
mallwright
1/13/2020
这同样适用于 Box、Rc、Arc 吗?
0赞
silvioprog
1/17/2020
是的,确实如此。您可以将它们组合在一起,例如:... .Rc<Cell<i32>>
y: Rc::new(Cell::new(0)),
评论