Struct println中的可变和不可变引用
我是一个新手,遇到了一些初学者的问题,我想与互联网上的其他人分享我的解决方案,而我在现有的线程中没有找到这些解决方案。我想知道是否有一种更可靠的方法 我想打印出矩形的高度、宽度和面积Struct println中的可变和不可变引用,struct,rust,ownership,Struct,Rust,Ownership,我是一个新手,遇到了一些初学者的问题,我想与互联网上的其他人分享我的解决方案,而我在现有的线程中没有找到这些解决方案。我想知道是否有一种更可靠的方法 我想打印出矩形的高度、宽度和面积 struct Rectangle { height: u32, width: u32, area: u32, } impl Rectangle{ fn area(& mut self) -> u32 { self.area = self.height
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());
}
这给了我一个错误,不能作为不可变的借来,因为它也是作为可变的借来的
我的解决方案
println!("Rectangle has height {1} width {2} and area {0}", rect1.area(), rect1.height, rect1.width);
更改println中的顺序代码>语句
我知道您不能同时拥有不可变引用和可变引用,因为不可变引用不希望值发生更改。看见但为什么我的解决方案有效?显然,在相同的println中仍然有一个可变和不可变的引用代码>语句,但顺序已更改
但为什么我的解决方案有效?显然,在同一个println中仍然有一个可变和不可变的引用!语句,但顺序已更改
不!问题是,area()
需要一个可变借用,但不保留一个,因为它返回一个拥有的值(u32
),而不是一个借用的值(&u32
),所以借用只在调用范围内持续,并且在调用返回后释放
现在你可以期待同样的高度
和宽度
,陷阱是println代码>隐式地借用了它的参数,所以当您println!(“{}”,rect.height)
它沿着参数(“,&rect.height”)的行编译成某种东西
,创建一个借阅,直到格式化过程结束
现在,因为借用是隐式的,所以您不能取消属性(*rec.height
)的引用,因为该属性将是&*rec.height
,其中rec.height
仍然是u8,但是还有一种方法:
块始终是值表达式,并计算值表达式上下文中的最后一个表达式。如果确实需要,可以使用此命令强制移动值
这意味着&{rec.height}
将首先将值复制(或移动)出结构,然后借用该副本。因此,您还可以通过以下方式修复调用:
println!(“矩形有高度{}宽度{}和面积{},{rect1.height},{rect1.width},rect1.area());
这将首先复制这两个属性,然后是println
将隐式借用它们,但它不需要借用结构本身,从而导致三个非重叠借用
在这种情况下,您可能需要添加一条注释来解释您为什么这样做,因为它是。。。奇怪
再说一遍,我认为你的区域是一个反模式,所以YMMV
但为什么我的解决方案有效?显然,在同一个println中仍然有一个可变和不可变的引用!语句,但顺序已更改
不!问题是,area()
需要一个可变借用,但不保留一个,因为它返回一个拥有的值(u32
),而不是一个借用的值(&u32
),所以借用只在调用范围内持续,并且在调用返回后释放
现在你可以期待同样的高度
和宽度
,陷阱是println代码>隐式地借用了它的参数,所以当您println!(“{}”,rect.height)
它沿着参数(“,&rect.height”)的行编译成某种东西
,创建一个借阅,直到格式化过程结束
现在,因为借用是隐式的,所以您不能取消属性(*rec.height
)的引用,因为该属性将是&*rec.height
,其中rec.height
仍然是u8,但是还有一种方法:
块始终是值表达式,并计算值表达式上下文中的最后一个表达式。如果确实需要,可以使用此命令强制移动值
这意味着&{rec.height}
将首先将值复制(或移动)出结构,然后借用该副本。因此,您还可以通过以下方式修复调用:
println!(“矩形有高度{}宽度{}和面积{},{rect1.height},{rect1.width},rect1.area());
这将首先复制这两个属性,然后是println
将隐式借用它们,但它不需要借用结构本身,从而导致三个非重叠借用
在这种情况下,您可能需要添加一条注释来解释您为什么这样做,因为它是。。。奇怪
再说一遍,我认为你的区域是一个反模式,所以YMMV.嗯,它甚至不是一个反模式,更像是反常识。我希望这只是这篇文章的一个人为的例子。面积应该在构造时计算(存储和引用),或者在请求时计算(动态计算返回新值,而不是引用)@Rbjz在写评论时,我将面积作为某种懒惰计算的替代品,例如,一些计算成本很高的东西,如果你从未使用过它,你就不想计算它,但一旦计算完毕,您就希望保持该值不变。因此称之为反模式。我同意面积本身毫无意义,因为它是一个相当便宜的计算。好吧,它甚至不是一个反模式,更像是反常识。我希望这只是这篇文章的一个人为的例子。面积应该在构造时计算(存储和引用),或者在请求时计算(动态计算返回新值,而不是引用)@Rbjz在写评论时,我将面积作为某种懒惰计算的替代品,例如,一些计算成本很高的东西,如果你从未使用过它,你就不想计算它,但一旦计算完毕,您就希望保持该值不变。因此称之为反模式。我同意面积本身毫无意义,因为它是一个相当便宜的计算。我不得不说,借用的顺序让我感到有些困难:)Rust在这方面取得了一些进展。我也一样。我不得不说,借款的顺序让我受了几次打击:)Rust在这方面取得了一些进展。我也是。
println!("Rectangle has height {1} width {2} and area {0}", rect1.area(), rect1.height, rect1.width);