简体   繁体   English

println 中的可变和不可变引用

[英]Mutable and Immutable reference inside println

I am fairly new to Rust and encountered some beginner problems and want to share my solution with others around the internet that I haven't found in existing threads.我对 Rust 还很陌生,遇到了一些初学者问题,想与互联网上的其他人分享我在现有线程中找不到的解决方案。 I wonder if there is a more Rust approach to it.我想知道是否有更多的Rust方法。

I want to print out the height, width and area of a Rectangle.我想打印出矩形的高度、宽度和面积。

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

which gives me the error 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

My solution我的解决方案

println!("Rectangle has height {1} width {2} and area {0}", rect1.area(), rect1.height, rect1.width);

changing the order in the println!更改println! statement.陈述。

I know that you cannot have an immutable and mutable reference at the same time, because the immutable reference does not expect the values to be changed.我知道您不能同时拥有不可变和可变引用,因为不可变引用不期望值被更改。 See here .这里 But why does my solution work?但为什么我的解决方案有效? Clearly, there still is a mutable and immutable reference in the same println!显然,在同一个println! statement but with changed order.声明但更改了顺序。

But why does my solution work?但为什么我的解决方案有效? Clearly, there still is a mutable and immutable reference in the same println.显然,在同一个 println 中仍然存在一个可变和不可变的引用。 statement but with changed order.声明但更改了顺序。

Nope!没有! The thing is area() requires a mutable borrow but does not keep one , since it returns an owned value ( u32 ) rather than a borrowed one ( &u32 ), so the borrow only lasts for the extent of the call and is released once the call returns.问题是area()需要一个可变借用但不保留一个,因为它返回一个拥有的值( u32 )而不是一个借用的值( &u32 ),所以借用只在调用范围内持续,一旦调用返回。

Now you could expect the same of height and width , the trap is that println!现在你可以期待heightwidth相同,陷阱就是println! implicitly borrows its parameters, so when you println,("{}". rect.height) it compiles to something along the lines of Arguments("", &rect.height) , creating a borrow until the end of the formatting process.隐式借用其参数,因此当您println,("{}". rect.height)时,它会编译为Arguments("", &rect.height)行中的内容,创建一个借用直到格式化过程结束。

Now because the borrow is implicit you can't deref' the attribute ( *rec.height ) as that would be &*rec.height where rec.height is still a u8, however there is an other method which isblock expressions :现在,因为借用是隐式的,所以您不能取消引用属性 ( *rec.height ),因为这将是&*rec.height ,其中rec.height仍然是 u8,但是还有另一种方法是块表达式

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.如果确实需要,这可用于强制移动值。

This means that &{rec.height} will first copy (or move) the value out of the structure, then borrow that copy.这意味着&{rec.height}将首先将值复制(或移动)出结构,然后借用该副本。 Therefore you can also fix the call by writing:因此,您还可以通过以下方式修复呼叫:

println!("Rectangle has height {} width {} and area {}", {rect1.height}, {rect1.width}, rect1.area());

That will copy the two attributes out first, then println!这将首先复制这两个属性,然后println! will implicitly borrow them, but it won't need to borrow the structure itself leading to three non-overlapping borrows.将隐式借用它们,但不需要借用结构本身导致三个不重叠的借用。

In that case, you may want to add a comment to explain why you're doing that as it's... odd.在这种情况下,您可能需要添加评论来解释您为什么这样做,因为它......很奇怪。

Then again, I think your area is an anti-pattern, so YMMV.再说一次,我认为您的area是反模式,所以 YMMV。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 这个不可变结构应该是一个可变类吗? - Should this immutable struct be a mutable class? 为什么forEach中的迭代器对于结构是不可变的,但对于类却是可变的? - Why are iterators in forEach immutable for a struct but mutable for a class? 不可变结构比可变结构有什么好处? - What are the benefits of an immutable struct over a mutable one? Julia中的不可变vs结构和类型vs可变结构 - immutable vs struct and type vs mutable struct in Julia 从外部代码的角度来看,可变结构是不可变的呢? - What about a mutable struct that's immutable from the standpoint of external code? 使用结构本身的值更新结构给出:“不能将 `*self` 借为可变的,因为它也被借为不可变的” - update struct using a value from the struct itself gives: "cannot borrow `*self` as mutable because it is also borrowed as immutable" 如何在类定义中使结构不可变 - How to make struct immutable inside a class definition 非常量成员引用在 const object 上是可变的吗? - Non-const member reference is mutable on const object? 无法在C#中使结构内的值类型可变 - Not able to make the value types inside a structure as mutable in c# 为什么不能在 Julia 的 function 中定义可变结构 - Why mutable struct cannot be defined inside a function in Julia
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM