未针对移动值调用克隆?

ter*_*tra 5 rust

我试图理解 Copy 如何与 Rust 中的移动语义交互。我希望这个程序能够克隆该对象,但事实并非如此。我有 Rust 1.0.0-beta。

#[derive(Debug)]                                  
struct X {
  y : i32,
}

impl Clone for X {
  fn clone(&self) -> X { 
    println!("clone");
    X { y: 4 }
  } 
}

impl Copy for X { }  

fn doit(x : X) {     
  println!("doit {:?}", x);
}

fn main() { 
  let z = X { y: 5 };    
  println!("main {:?}", z);
  doit(z);        
  println!("main {:?}", z);
}
Run Code Online (Sandbox Code Playgroud)

这是我的困惑:如果 X 不是“复制”,doit 会取得对象 z 的所有权并将其放在范围末尾。然后,main 中的第二个 println 会抱怨,因为 z 被移动了。美好的。但是,现在我已将 X 标记为 Copy 并提供了克隆方法。我预计克隆方法将用于为 doit 提供它自己的 z 副本,从而允许我在 doit 之后继续使用 z。那不会发生。

我的理解哪里错了?

小智 3

Clone没什么特别的。这只是一个普通的图书馆特征。你可以自己定义!

因此,.clone()仅当您显式调用它时才使用它。复制和移动都与 没有任何关系Clone。当您调用 时doit(z)z在某种意义上是复制的Copy,这意味着在幕后进行字节复制。如果您想克隆以将其传递给doit,则编写:

doit(z.clone());
Run Code Online (Sandbox Code Playgroud)

  • @terpstra 像这样看它:`Clone` 是一个可以给出类型的通用属性。它说“通过一些工作,可以复制这种类型的值”。如果它在逻辑上有效,那么您几乎*总是*可以实现“克隆”。“复制”更专业;它说“您可以通过忽略 `Clone::clone` 并仅使用 `memcpy` 字节来创建副本”,但要求这实际上会创建一个有效的副本(这并不总是正确的)。 (4认同)