println 中的可变和不可变引用
Mutable and Immutable reference inside println
我对 Rust 还很陌生,遇到了一些初学者问题,想与互联网上的其他人分享我在现有线程中没有找到的解决方案。我想知道是否有更 Rust 的方法。
我想打印出一个矩形的高、宽和面积。
struct Rectangle {
height: u32,
width: u32,
area: u32,
}
impl Rectangle{
fn area(& mut self) -> u32 {
self.area = self.height * self.width;
return self.area
}
}
fn main() {
let mut rect1 = Rectangle {height: 20, width: 30, area: 0};
println!("Rectangle has height {} width {} and area {}", rect1.height, rect1.width, rect1.area());
}
这给了我错误 cannot borrow as immutable because it is also borrowed as mutable
error[E0502]: cannot borrow `rect1` as mutable because it is also borrowed as immutable
--> src/main.rs:17:88
|
17 | println!("Rectangle has height {} width {} and area {}", rect1.height, rect1.width, rect1.area());
| -----------------------------------------------------------------------------------^^^^^^^^^^^^--
| | | |
| | | mutable borrow occurs here
| | immutable borrow occurs here
| immutable borrow later used here
我的解决方案
println!("Rectangle has height {1} width {2} and area {0}", rect1.area(), rect1.height, rect1.width);
更改 println!
语句中的顺序。
我知道您不能同时拥有不可变引用和可变引用,因为不可变引用不希望更改值。参见 here。但为什么我的解决方案有效?显然,在同一个 println!
语句中仍然有一个可变和不可变的引用,但顺序改变了。
But why does my solution work? Clearly, there still is a mutable and immutable reference in the same println! statement but with changed order.
不!问题是 area()
需要一个可变的借用 但不保留一个 ,因为它 returns 是一个拥有的值 (u32
) 而不是借用的(&u32
),因此借用仅持续调用的范围,并在调用 returns.
后释放
现在你可以期望 height
和 width
相同,陷阱是 println!
隐式地 借用了它的参数,所以当你 println!("{}", rect.height)
它编译成类似于 Arguments("", &rect.height)
的东西,在格式化过程结束之前创建借用。
现在因为借用是隐式的,所以你不能取消引用属性 (*rec.height
),因为那将是 &*rec.height
,其中 rec.height
仍然是一个 u8,但是有一个另一种方法是 block expressions:
Blocks are always value expressions and evaluate the last expression in value expression context. This can be used to force moving a value if really needed.
这意味着 &{rec.height}
将首先复制(或移动)结构中的值,然后借用该副本。因此,您还可以通过以下方式修复调用:
println!("Rectangle has height {} width {} and area {}", {rect1.height}, {rect1.width}, rect1.area());
这将首先复制两个属性,然后 println!
将隐式借用它们,但不需要借用结构本身导致三个非重叠借用。
在这种情况下,您可能需要添加评论来解释您这样做的原因,因为它...很奇怪。
再一次,我认为你的 area
是一个反模式,所以 YMMV。
我对 Rust 还很陌生,遇到了一些初学者问题,想与互联网上的其他人分享我在现有线程中没有找到的解决方案。我想知道是否有更 Rust 的方法。
我想打印出一个矩形的高、宽和面积。
struct Rectangle {
height: u32,
width: u32,
area: u32,
}
impl Rectangle{
fn area(& mut self) -> u32 {
self.area = self.height * self.width;
return self.area
}
}
fn main() {
let mut rect1 = Rectangle {height: 20, width: 30, area: 0};
println!("Rectangle has height {} width {} and area {}", rect1.height, rect1.width, rect1.area());
}
这给了我错误 cannot borrow as immutable because it is also borrowed as mutable
error[E0502]: cannot borrow `rect1` as mutable because it is also borrowed as immutable
--> src/main.rs:17:88
|
17 | println!("Rectangle has height {} width {} and area {}", rect1.height, rect1.width, rect1.area());
| -----------------------------------------------------------------------------------^^^^^^^^^^^^--
| | | |
| | | mutable borrow occurs here
| | immutable borrow occurs here
| immutable borrow later used here
我的解决方案
println!("Rectangle has height {1} width {2} and area {0}", rect1.area(), rect1.height, rect1.width);
更改 println!
语句中的顺序。
我知道您不能同时拥有不可变引用和可变引用,因为不可变引用不希望更改值。参见 here。但为什么我的解决方案有效?显然,在同一个 println!
语句中仍然有一个可变和不可变的引用,但顺序改变了。
But why does my solution work? Clearly, there still is a mutable and immutable reference in the same println! statement but with changed order.
不!问题是 area()
需要一个可变的借用 但不保留一个 ,因为它 returns 是一个拥有的值 (u32
) 而不是借用的(&u32
),因此借用仅持续调用的范围,并在调用 returns.
现在你可以期望 height
和 width
相同,陷阱是 println!
隐式地 借用了它的参数,所以当你 println!("{}", rect.height)
它编译成类似于 Arguments("", &rect.height)
的东西,在格式化过程结束之前创建借用。
现在因为借用是隐式的,所以你不能取消引用属性 (*rec.height
),因为那将是 &*rec.height
,其中 rec.height
仍然是一个 u8,但是有一个另一种方法是 block expressions:
Blocks are always value expressions and evaluate the last expression in value expression context. This can be used to force moving a value if really needed.
这意味着 &{rec.height}
将首先复制(或移动)结构中的值,然后借用该副本。因此,您还可以通过以下方式修复调用:
println!("Rectangle has height {} width {} and area {}", {rect1.height}, {rect1.width}, rect1.area());
这将首先复制两个属性,然后 println!
将隐式借用它们,但不需要借用结构本身导致三个非重叠借用。
在这种情况下,您可能需要添加评论来解释您这样做的原因,因为它...很奇怪。
再一次,我认为你的 area
是一个反模式,所以 YMMV。