问题描述
我是 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());
}
这给了我错误不能借为不可变,因为它也被借为可变
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.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.width);
更改 println!
语句中的顺序。
我知道你不能同时拥有一个不可变和可变的引用,因为不可变的引用不希望值被改变。见here。但为什么我的解决方案有效?很明显,在同一个 println!
语句中仍然有一个可变和不可变的引用,但顺序改变了。
解决方法
但是为什么我的解决方案有效?显然,在同一个 println! 中仍然有一个可变和不可变的引用!声明但更改了顺序。
不!事情是 area()
需要一个可变借用 但不保留一个,因为它返回一个拥有的值(u32
)而不是一个借用的值(&u32
) ,因此借用仅持续调用的范围,并在调用返回后释放。
现在您可以期望 height
和 width
相同,陷阱是 println!
隐式借用其参数,因此当您 {{1} } 它编译成类似 println!("{}",rect.height)
的东西,在格式化过程结束之前创建借用。
现在因为借用是隐式的,所以你不能取消引用属性 (Arguments("",&rect.height)
),因为它是 *rec.height
,其中 &*rec.height
仍然是一个 u8,但是还有另一种方法这是block expressions:
块总是值表达式并计算值表达式上下文中的最后一个表达式。如果确实需要,这可用于强制移动值。
这意味着 rec.height
将首先复制(或移动)结构中的值,然后借用该副本。因此,您还可以通过编写以下内容来修复呼叫:
&{rec.height}
这将首先复制两个属性,然后 println!("Rectangle has height {} width {} and area {}",{rect1.height},{rect1.width},rect1.area());
将隐式借用它们,但不需要借用结构本身导致三个不重叠的借用。
在这种情况下,您可能需要添加评论来解释您为什么要这样做,因为它......很奇怪。
再说一次,我认为您的 println!
是一种反模式,所以 YMMV。