Reference 如何将可变引用更新为不可复制类型?
我想做一些像Reference 如何将可变引用更新为不可复制类型?,reference,copy,rust,move,mutable,Reference,Copy,Rust,Move,Mutable,我想做一些像 impl Widget { fn foo(self, rhs: Widget) -> Self { // Some stuff } fn update(&mut self, rhs: Widget) { *self = (*self).foo(rhs) } } 但编译器抱怨“无法脱离借用的上下文”。正确的方法是什么?换一种方法: impl Widget { fn op(mut self, rh
impl Widget {
fn foo(self, rhs: Widget) -> Self {
// Some stuff
}
fn update(&mut self, rhs: Widget) {
*self = (*self).foo(rhs)
}
}
但编译器抱怨“无法脱离借用的上下文”。正确的方法是什么?换一种方法:
impl Widget {
fn op(mut self, rhs: Widget) -> Self {
self.update(rhs);
self
}
fn update(&mut self, rhs: Widget) {
// Some stuff
}
}
您不能移出借用的指针,因为移动会使源不可用,但由于您不拥有源,该信息必须传播回所有者,Rust不支持这一点
您可能会说“但是在函数返回之前,我正在为
*self
赋值!”。问题是,如果在移动和分配之间出现恐慌,*self
仍然没有有效值。如果掉落self
不是不可操作的(尽管Rust并不关心掉落是否是不可操作的),这尤其有问题。用另一种方法:
impl Widget {
fn op(mut self, rhs: Widget) -> Self {
self.update(rhs);
self
}
fn update(&mut self, rhs: Widget) {
// Some stuff
}
}
您不能移出借用的指针,因为移动会使源不可用,但由于您不拥有源,该信息必须传播回所有者,Rust不支持这一点
您可能会说“但是在函数返回之前,我正在为*self
赋值!”。问题是,如果在移动和分配之间出现恐慌,*self
仍然没有有效值。如果掉落self
不是不可操作的(尽管Rust并不关心掉落是否是不可操作的)。一个选项是使用板条箱,它提供的take
功能完全满足您的要求:
take
允许从&mut T T
中提取T
,使用它做任何事情,包括消费它,并生成另一个T
放回&mut T T
正如所指出的,这样做的问题是,如果发生死机,&mut
引用将处于无效状态,这可能导致未定义的行为。take_mut
方法是:
在take
期间,如果出现恐慌,整个过程将退出,因为没有有效的T
放回&mut T T
下面是使用take
的代码:
extern crate take_mut;
struct Widget;
impl Widget {
fn foo(self, rhs: Widget) -> Self {
self
}
fn update(&mut self, rhs: Widget) {
take_mut::take(self, |s| s.foo(rhs));
}
}
一种选择是使用板条箱,它提供了take
功能,可以完全满足您的需求:
take
允许从&mut T T
中提取T
,使用它做任何事情,包括消费它,并生成另一个T
放回&mut T T
正如所指出的,这样做的问题是,如果发生死机,&mut
引用将处于无效状态,这可能导致未定义的行为。take_mut
方法是:
在take
期间,如果出现恐慌,整个过程将退出,因为没有有效的T
放回&mut T T
下面是使用take
的代码:
extern crate take_mut;
struct Widget;
impl Widget {
fn foo(self, rhs: Widget) -> Self {
self
}
fn update(&mut self, rhs: Widget) {
take_mut::take(self, |s| s.foo(rhs));
}
}
假设我不能或不想这样做(考虑到这需要一个完全不同的设计,并且没有实际的理由说明另一种方法不应该同样有效),这是一个很好的观点。我没有考虑如果有恐慌会发生什么。假设我不能或不想(因为这需要一个完全不同的设计,没有实际的理由为什么另一种方式也不工作)。这是一个很好的观点。我没有想到会发生什么,如果有恐慌。