我在Rust中有一个枚举,其中有一个值为String
。这可以通过这个简单的例子来证明:
#[derive(Clone, Copy)]
enum Simple {
Error(String),
Okay,
Foo([u32; 5]),
}
fn main() {
let x = Simple::Error(String::from("blah"));
let y = x.clone();
}
上面的枚举值Foo
表示我使用的大约10个其他枚举,它们采用可复制类型或它们的数组。编译器似乎没有抱怨它们,只有导致这种情况的Error(String)
:
error[E0204]: the trait `Copy` may not be implemented for this type
--> src/main.rs:1:17
|
1 | #[derive(Clone, Copy)]
| ^^^^
2 | enum Simple {
3 | Error(String),
| ------ this field does not implement `Copy`
由于某种原因,String
不可复制。我不明白这一点。如何为只有一个类型的枚举实现Clone
,而对其余类型使用默认impl时会出现问题?
答案 0 :(得分:25)
Copy
指定使得按位复制创建有效实例而不会使原始实例无效的类型。
String
不是这样,因为String
包含指向堆上字符串数据的指针,并假定它具有该数据的唯一所有权。删除String
时,它会释放堆上的数据。如果您已经对String
进行了按位复制,则两个实例都会尝试释放相同的内存块,即未定义的行为。
由于String
未实现Copy
,您的enum
无法实现Copy
,因为编译器强制执行Copy
类型仅由Copy
个数据成员组成。
Clone
仅提供标准clone
方法,由每个实现者决定如何实现它。 String
确实实施了Clone
,因此您可以将#[derive(Clone)]
放在enum
上。
答案 1 :(得分:0)
我做了一些探索,以了解手动实现枚举是什么样子。我想到了这一点,但请记住,您也可以按照其他地方的说明进行#[derive(Clone)]
,编译器会为您完成。
enum Simple {
Error(String),
Okay,
Foo([u32; 5]),
}
impl Clone for Simple {
fn clone(&self) -> Simple {
match self {
Error(a) => Error(a.to_string()),
Okay => Okay,
Foo(a) => Foo(a.clone()),
}
}
}