我该如何在可变引用的结构体中替换字段的新值?

55

我有一个带有字段的结构体:

struct A {
    field: SomeType,
}

如果给定一个&mut A,我该如何移动field的值并交换一个新值?

fn foo(a: &mut A) {
    let mut my_local_var = a.field;
    a.field = SomeType::new();

    // ...
    // do things with my_local_var
    // some operations may modify the NEW field's value as well.
}

最终目标是实现一个等同于get_and_set()操作的功能。在这种情况下,我不担心并发问题。

2个回答

63

使用std::mem::swap()函数。

fn foo(a: &mut A) {
    let mut my_local_var = SomeType::new();
    mem::swap(&mut a.field, &mut my_local_var);
}

或者std::mem::replace()

fn foo(a: &mut A) {
    let mut my_local_var = mem::replace(&mut a.field, SomeType::new());
}    

10
或者 let mut my_local_var = mem::replace(&mut a.field, SomeType::new());。这两者完全等效。 - Chris Morgan

37
如果你的类型实现了 Default,那么你可以使用 std::mem::take
#[derive(Default)]
struct SomeType;

fn foo(a: &mut A) {
    let mut my_local_var = std::mem::take(&mut a.field);
}

如果您的字段恰好是 Option,则有一种特定的方法可以使用 — Option::take

struct A {
    field: Option<SomeType>,
}

fn foo(a: &mut A) {
    let old = a.field.take();
    // a.field is now None, old is whatever a.field used to be
}

Option::take的实现使用了mem::take,就像上面更通用的答案所展示的那样,但它为您进行了很好的封装。

pub fn take(&mut self) -> Option<T> {
    mem::take(self)
}

另请参见:


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接