Trait core::marker::Copy1.0.0[][src]

pub trait Copy: Clone { }
Expand description

只需复制位即可复制其值的类型。

默认情况下,变量绑定具有移动语义。换句话说:

#[derive(Debug)]
struct Foo;

let x = Foo;

let y = x;

// `x` 已移至 `y`,因此无法使用

// println!("{:?}", x); // error: use of moved value
Run

但是,如果类型实现 Copy,则它具有复制语义:

// 我们可以派生一个 `Copy` 实现。
// `Clone` 也是必需的,因为它是 `Copy` 的特征。
#[derive(Debug, Copy, Clone)]
struct Foo;

let x = Foo;

let y = x;

// `y` 是 `x` 的副本

println!("{:?}", x); // A-OK!
Run

重要的是要注意,在这两个示例中,唯一的区别是分配后是否允许您访问 x。 在后台,复制和移动都可能导致将位复制到内存中,尽管有时会对其进行优化。

如何实现 Copy?

有两种方法可以在您的类型上实现 Copy。最简单的是使用 derive:

#[derive(Copy, Clone)]
struct MyStruct;
Run

您还可以手动实现 CopyClone:

struct MyStruct;

impl Copy for MyStruct { }

impl Clone for MyStruct {
    fn clone(&self) -> MyStruct {
        *self
    }
}
Run

两者之间的区别很小: derive 策略还将 Copy 绑定在类型参数上,这并不总是需要的。

CopyClone 有什么区别?

复制是隐式发生的,例如作为工作 y = x 的一部分。Copy 的行为不可重载; 它始终是简单的按位复制。

克隆是一个明确的动作 x.clone()Clone 的实现可以提供安全复制值所需的任何特定于类型的行为。 例如,用于 StringClone 的实现需要在堆中复制指向字符串的缓冲区。 String 值的简单按位副本将仅复制指针,从而导致该行向下双重释放。 因此,StringClone,但不是 Copy

CloneCopy 的特征,因此 Copy 的所有内容也必须实现 Clone。 如果类型为 Copy,则其 Clone 实现仅需要返回 *self (请参见上面的示例)。

什么时候可以输入 Copy?

如果类型的所有组件都实现 Copy,则它可以实现 Copy。例如,此结构体可以是 Copy:

#[derive(Copy, Clone)]
struct Point {
   x: i32,
   y: i32,
}
Run

一个结构体可以是 Copy,而 i32Copy,因此 Point 有资格成为 Copy。 相比之下,考虑

struct PointList {
    points: Vec<Point>,
}
Run

结构体 PointList 无法实现 Copy,因为 Vec<T> 不是 Copy。如果尝试派生 Copy 实现,则会收到错误消息:

the trait `Copy` may not be implemented for this type; field `points` does not implement `Copy`

共享引用 (&T) 也是 Copy,因此,即使类型中包含 04 不是*Copy 类型的共享引用 T,也可以是 Copy。 考虑下面的结构体,它可以实现 Copy,因为它从上方仅对我们的非 Copy 类型 PointList 持有一个 shared 引用:

#[derive(Copy, Clone)]
struct PointListWrapper<'a> {
    point_list_ref: &'a PointList,
}
Run

什么时候我的类型不能为 Copy?

某些类型无法安全复制。例如,复制 &mut T 将创建一个别名可变引用。 复制 String 将重复管理 String 缓冲区,从而导致双重释放。

概括后一种情况,任何实现 Drop 的类型都不能是 Copy,因为它除了管理自己的 size_of::<T> 字节外还管理一些资源。

果您尝试在包含非 Copy 数据的结构或枚举上实现 Copy,则会收到 E0204 错误。

什么时候我的类型应该是 Copy?

一般来说,如果您的类型可以实现 Copy,则应该这样做。 但是请记住,实现 Copy 是您类型的公共 API 的一部分。 如果该类型将来可能变为非 Copy,则最好现在省略 Copy 实现,以避免 API 发生重大更改。

其他实现者

下面列出的实现者 之外,以下类型还实现 Copy:

  • 函数项类型 (即,为每个函数定义的不同类型)
  • 函数指针类型 (例如 fn() -> i32)
  • 如果项类型也实现 Copy (例如 [i32; 123456]),则所有大小的数组类型
  • 如果每个组件还实现 Copy (例如 ()(i32, bool)),则为元组类型
  • 闭包类型,如果它们没有从环境中捕获任何值,或者所有此类捕获的值本身都实现了 Copy。 请注意,由共享引用捕获的变量始终实现 Copy (即使引用对象没有实现),而由变量引用捕获的变量从不实现 Copy

Implementors

This is supported on AArch64 only.
This is supported on AArch64 only.
This is supported on AArch64 only.
This is supported on AArch64 only.
This is supported on AArch64 only.
This is supported on AArch64 only.
This is supported on AArch64 only.
This is supported on AArch64 only.
This is supported on AArch64 only.
This is supported on AArch64 only.
This is supported on AArch64 only.
This is supported on ARM only.
This is supported on ARM only.
This is supported on ARM only.
This is supported on ARM only.
This is supported on PowerPC or PowerPC-64 only.
This is supported on PowerPC or PowerPC-64 only.
This is supported on PowerPC or PowerPC-64 only.
This is supported on PowerPC or PowerPC-64 only.
This is supported on WebAssembly only.
This is supported on x86 or x86-64 only.
This is supported on x86 or x86-64 only.
This is supported on x86 or x86-64 only.
This is supported on x86 or x86-64 only.
This is supported on x86 or x86-64 only.
This is supported on x86 or x86-64 only.
This is supported on x86 or x86-64 only.
This is supported on x86 or x86-64 only.
This is supported on x86 or x86-64 only.
This is supported on x86 or x86-64 only.
This is supported on x86 or x86-64 only.
This is supported on x86 or x86-64 only.
This is supported on x86 or x86-64 only.

共享的引用可以复制,但是可变引用 不能!