gpt4 book ai didi

rust - 如何在将字段移动到新变体时更改枚举变体?

转载 作者:行者123 更新时间:2023-11-29 07:42:41 24 4
gpt4 key购买 nike

我想在不进行任何克隆的情况下将旧变体的字段移动到新变体的同时更新枚举变体:

enum X {
X1(String),
X2(String),
}

fn increment_x(x: &mut X) {
*x = match *x {
X::X1(s) => X::X2(s),
X::X2(s) => X::X1(s),
}
}

这不起作用,因为我们不能从 &mut X 移动 s:

error[E0507]: cannot move out of borrowed content
--> src/lib.rs:7:16
|
7 | *x = match *x {
| ^^
| |
| cannot move out of borrowed content
| help: consider removing the `*`: `x`
8 | X::X1(s) => X::X2(s),
| - data moved here
9 | X::X2(s) => X::X1(s),
| - ...and here

请不要建议诸如实现 enum X { X1, X2 } 和使用 struct S { variant: X, str: String } 等。这是一个简化的示例,假设变体中有许多其他字段,并且想要将一个字段从一个变体移动到另一个变体。

最佳答案

This doesn't work because we can't move s from &mut X.

那么不要那样做...按值获取结构并返回一个新结构:

enum X {
X1(String),
X2(String),
}

fn increment_x(x: X) -> X {
match x {
X::X1(s) => X::X2(s),
X::X2(s) => X::X1(s),
}
}

最终,编译器会保护您,因为如果您可以将字符串移出枚举,那么它将处于某种半构造状态。如果函数在那一刻 panic ,谁将负责释放字符串?它应该释放枚举中的字符串还是局部变量中的字符串?它不能同时存在,因为双重释放是一个内存安全问题。

如果您必须在可变引用上实现它,您可以临时在其中存储一个虚拟值:

use std::mem;

fn increment_x_inline(x: &mut X) {
let old = mem::replace(x, X::X1(String::new()));
*x = increment_x(old);
}

创建一个空的 String 还不错(只是一些指针,没有堆分配),但这并不总是可行的。在这种情况下,您可以使用 Option:

fn increment_x_inline(x: &mut Option<X>) {
let old = x.take();
*x = old.map(increment_x);
}

另见:

关于rust - 如何在将字段移动到新变体时更改枚举变体?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36557412/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com