如何为包含 String (或任何未实现 Copy 的类型)的类型实现 Copy 和 Clone?

我在 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?

43766 次浏览

Copy

Copy designates types for which making a bitwise copy creates a valid instance without invalidating the original instance.

This isn't true for String, because String contains a pointer to the string data on the heap and assumes it has unique ownership of that data. When you drop a String, it deallocates the data on the heap. If you had made a bitwise copy of a String, then both instances would try to deallocate the same memory block, which is undefined behaviour.

Since String doesn't implement Copy, your ABC2 cannot implement Copy either because the compiler enforces that Copy types are composed only of Copy data members.

Clone

Clone merely provides a standard clone method, and it's up to each implementor to decide how to implement it. String does implement Clone, so you can put #[derive(Clone)] on your enum.

I did some exploring to see what a manual implementation would look like for an enum. I came up with this, but keep in mind you can also do #[derive(Clone)] as stated elsewhere and the compiler will do this for you.

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()),
}
}
}