rust 拷贝和克隆之间有何区别?

uz75evzq  于 2023-01-21  发布在  其他
关注(0)|答案(5)|浏览(194)

This issue似乎暗示它只是一个实现细节(memcpy与???),但我找不到任何对差异的明确描述。

carvr3hs

carvr3hs1#

Clone设计用于任意复制:类型TClone实现可以执行创建新T所需的任意复杂操作。它是一个普通trait(而不是在序言中),因此需要像普通trait一样使用方法调用等。
Copy trait表示可以通过memcpy安全复制的值:像重新分配和按值传递参数给函数这样的事情总是memcpy s,所以对于Copy类型,编译器知道它不需要考虑那些a move

8cdiaqws

8cdiaqws2#

主要的区别是克隆是显式的,隐式表示法意味着非Copy类型的移动。

// u8 implements Copy
let x: u8 = 123;
let y = x;
// x can still be used
println!("x={}, y={}", x, y);

// Vec<u8> implements Clone, but not Copy
let v: Vec<u8> = vec![1, 2, 3];
let w = v.clone();
//let w = v // This would *move* the value, rendering v unusable.

顺便说一下,每个Copy类型也需要是Clone,但是,它们不需要做同样的事情!对于您自己的类型,.clone()可以是您选择的任意方法,而隐式复制总是触发memcpy,而不是clone(&self)实现。

bfnvny8b

bfnvny8b3#

如其他答复所述:

  • Copy是隐式的、廉价的,并且不能被重新实现(memcpy)。
  • Clone是显式,可能是昂贵的,且可以被任意地重新实现。

在讨论CopyClone时,有时候忽略了编译器如何使用移动与自动复制。例如:

#[derive(Debug, Clone, Copy)]
pub struct PointCloneAndCopy {
    pub x: f64,
}

#[derive(Debug, Clone)]
pub struct PointCloneOnly {
    pub x: f64,
}

fn test_copy_and_clone() {
    let p1 = PointCloneAndCopy { x: 0. };
    let p2 = p1; // because type has `Copy`, it gets copied automatically.
    println!("{:?} {:?}", p1, p2);
}

fn test_clone_only() {
    let p1 = PointCloneOnly { x: 0. };
    let p2 = p1; // because type has no `Copy`, this is a move instead.
    println!("{:?} {:?}", p1, p2);
}

Rust Playground
由于隐式复制,第一个示例(PointCloneAndCopy)在这里运行良好,但第二个示例(PointCloneOnly)会因在移动后使用而出错:

error[E0382]: borrow of moved value: `p1`
  --> src/lib.rs:20:27
   |
18 |     let p1 = PointCloneOnly { x: 0. };
   |         -- move occurs because `p1` has type `PointCloneOnly`, which does not implement the `Copy` trait
19 |     let p2 = p1;
   |              -- value moved here
20 |     println!("{:?} {:?}", p1, p2);
   |                           ^^ value borrowed here after move

为了避免隐式移动,我们可以显式调用let p2 = p1.clone();
这可能会引起how to force a move of a type which implements the Copy trait?的问题。

  • 简要答复:你不能/没有道理。*
fjaof16o

fjaof16o4#

就像这里写的。
复制是隐式发生的,例如作为赋值y = x的一部分。Copy的行为是不可重载的;它总是简单的逐位复制。
克隆是一个显式操作x.clone()Clone的实现可以提供安全复制值所需的任何类型特定的行为。例如,StringClone实现需要复制堆中指向的字符串缓冲区。String值的简单按位复制将仅复制指针,从而导致线上出现双释放。因此,StringClone,而不是Copy
CloneCopy的超特性,所以Copy的所有东西都必须实现Clone,如果类型是Copy,那么它的Clone实现只需要返回*self

xbp102n0

xbp102n05#

我发现这个解释很有帮助:
在Rust中,一些简单类型是"隐式可复制的",当你赋值它们或将它们作为参数传递时,接收方将得到一个副本,原始值保留在原处。对于其他类型,必须通过实现Clone trait和调用clone()方法显式地进行复制。
Clone trait定义了显式创建对象T的深层副本的能力。当我们为类型T调用Clone时,它会执行创建新T所需的所有任意复杂的操作。
rust中的Copy trait定义了隐式复制对象的能力。Copy行为是不可重载的。它总是简单的按位复制。这适用于具有固定大小并且完全存储在堆栈上的类型。
参考:https://intmain.co/difference-between-copy-and-clone-trait-in-rust

相关问题