如何为包含String的类型实现复制和克隆?

loc*_*cka 18 rust

我在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();
}
Run Code Online (Sandbox Code Playgroud)

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`
Run Code Online (Sandbox Code Playgroud)

出于某种原因,String不可复制.我不懂.Clone对于其他类型的枚举,如何使用默认impl进行其余操作时,如何实现枚举?

Fra*_*gné 28

复制

Copy 指定使按位复制创建有效实例而不使原始实例无效的类型.

但事实并非如此String,因为它String包含指向堆上字符串数据的指针,并假定它具有该数据的唯一所有权.删除a时String,它会释放堆上的数据.如果您已经对a进行了按位复制String,那么两个实例都会尝试释放相同的内存块,这是未定义的行为.

由于String未实现Copy,enum无法实现Copy,因为编译器强制执行Copy仅由Copy数据成员组成的类型.

克隆

Clone仅提供标准clone方法,由每个实现者决定如何实现它.String实施Clone,所以你可以穿上#[derive(Clone)]你的enum.

  • 我应该补充一点,我不明白为什么 String 在原则或实践中不能实现 Copy trait - QT 中的 QString 对象可以被复制,并且它们共享和维护一个内部缓冲区。如果副本做了一些可变的事情,缓冲区首先被克隆,所以其他副本仍然持有对原始缓冲区的引用。在 QT 中,通过引用传递以避免原子引用计数仍然是更好的做法,但无论如何复制是有效的。 (4认同)
  • @locka 因为 *`Copy` 指定了按位复制创建有效实例的类型*。复制这样一个字符串的位不能增加原子计数器,因为它不会再复制了。您可以选择您需要的保证。您可以[共享所有权](http://doc.rust-lang.org/std/rc/struct.Rc.html)、[跨线程共享所有权](http://doc.rust-lang.org/std /sync/struct.Arc.html), 实现[clone on write](http://doc.rust-lang.org/std/borrow/enum.Cow.html) 等。这对系统来说不是很好语言来为您做出决定(并负担您的代码)。 (3认同)
  • @cakraww `bitwise copy` 是使用 `memcpy` 或类似的所有字节的浅拷贝 /sf/ask/2992460761/ Between-memberwise-copy-bitwise-copy-shallow -复制并-d (2认同)

Bra*_*don 6

我做了一些探索,看看手动实现枚举会是什么样子。我想出了这个,但请记住,您也可以#[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()),
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 对于“#[derive(Clone, Copy)] pub enum ServerResponse { Ok(String), Err(String), }”,我得到“错误[E0204]:该类型可能无法实现特征“Copy””“Ok (字符串),| ------ 该字段未实现“复制”`。手动实现复制会导致类似的错误。 (6认同)