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());
}

这给了我错误不能借为不可变,因为它也被借为可变

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) ,因此借用仅持续调用的范围,并在调用返回后释放。

现在您可以期望 heightwidth 相同,陷阱是 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。