当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


Rust Copy用法及代码示例


本文简要介绍rust语言中 Trait std::marker::Copy 的用法。

用法

pub trait Copy: Clone { }

可以简单地通过复制位来复制其值的类型。

默认情况下,变量绑定有 'move semantics.' 换句话说:

#[derive(Debug)]
struct Foo;

let x = Foo;

let y = x;

// `x` has moved into `y`, and so cannot be used

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

但是,如果一个类型实现了 Copy ,则它改为具有 'copy semantics':

// We can derive a `Copy` implementation. `Clone` is also required, as it's
// a supertrait of `Copy`.
#[derive(Debug, Copy, Clone)]
struct Foo;

let x = Foo;

let y = x;

// `y` is a copy of `x`

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

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

如何实现 Copy

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

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

您还可以手动实现CopyClone

struct MyStruct;

impl Copy for MyStruct { }

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

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

CopyClone 有什么区别?

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

克隆是一个显式操作,x.clone() Clone 的实现可以提供安全复制值所需的任何 type-specific 行为。例如 String Clone 的实现需要复制堆中指向的字符串缓冲区。 String 值的简单按位复制只会复制指针,从而导致双倍释放。因此, String Clone 但不是 Copy

Clone Copy 的超特征,因此 Copy 的所有内容也必须实现 Clone 。如果一个类型是Copy,那么它的 Clone 实现只需要返回*self(见上面的例子)。

我的类型什么时候可以是 Copy

如果一个类型的所有组件都实现了Copy,则该类型可以实现Copy。例如,这个结构可以是 Copy

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

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

struct PointList {
    points: Vec<Point>,
}

结构 PointList 无法实现 Copy ,因为 Vec<T> 不是 Copy 。如果我们尝试派生 Copy 实现,我们会得到一个错误:

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

共享参考 (&T) 也是Copy, 所以一个类型可以是Copy,即使它拥有类型的共享引用T那是不是 Copy.考虑以下结构,它可以实现Copy, 因为它只持有一个共享参考对我们的非Copy类型PointList从上面:

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

什么时候不能我的类型是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, bool))
  • 闭包类型,如果它们没有从环境中捕获任何值,或者所有这些捕获的值都实现了Copy。请注意,共享引用捕获的变量始终实现Copy(即使引用对象没有),而可变引用捕获的变量从不实现Copy

外来类型的实现

1.27.0

__m128d 实现 Copy

1.27.0

__m256 实现 Copy

1.27.0

__m256d 实现 Copy

1.27.0

__m128i 实现 Copy

1.27.0

CpuidResult 实现 Copy

__m256bh 实现 Copy

__m512i 实现 Copy

__m128bh 实现 Copy

__m512d 实现 Copy

1.27.0

__m256i 实现 Copy

__m512bh 实现 Copy

__m512 实现 Copy

1.27.0

__m128 实现 Copy

相关用法


注:本文由纯净天空筛选整理自rust-lang.org大神的英文原创作品 Trait std::marker::Copy。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。