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` 的 super trait。
#[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您还可以手动实现 Copy
和 Clone
:
struct MyStruct;
impl Copy for MyStruct { }
impl Clone for MyStruct {
fn clone(&self) -> MyStruct {
*self
}
}
Run这两者之间有一个小小的区别: derive
策略还将 Copy
绑定在类型参数上,这并不总是需要的。
Copy
和 Clone
有什么区别?
Copy 是隐式发生的,例如作为赋值 y = x
的一部分。Copy
的行为不可重载; 它始终是简单的按位复制。
Clone 是一个显式操作,x.clone()
。Clone
的实现可以提供安全复制值所需的任何特定于类型的行为。
例如,用于 String
的 Clone
的实现需要在堆中复制指向字符串的缓冲区。
String
值的简单按位副本将仅复制指针,从而导致该行向下双重释放。
因此,String
是 Clone
,但不是 Copy
。
Clone
是 Copy
的一个 super trait,所以所有 Copy
的东西也必须实现 Clone
。
如果类型为 Copy
,则其 Clone
实现仅需要返回 *self
(请参见上面的示例)。
什么时候可以输入 Copy
?
如果类型的所有组件都实现 Copy
,则它可以实现 Copy
。例如,此结构体可以是 Copy
:
#[derive(Copy, Clone)]
struct Point {
x: i32,
y: i32,
}
Run一个结构体可以是 Copy
,而 i32
是 Copy
,因此 Point
有资格成为 Copy
。
相比之下,考虑
struct PointList {
points: Vec<Point>,
}
Run结构体 PointList
无法实现 Copy
,因为 Vec<T>
不是 Copy
。如果尝试派生 Copy
实现,则会收到错误消息:
the trait `Copy` cannot 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
。 请注意,由共享引用捕获的变量始终实现Copy
(即使引用对象没有实现),而由变量引用捕获的变量从不实现Copy
。
Implementors§
impl Copy for AsciiChar
impl Copy for std::cmp::Ordering
impl Copy for Infallible
impl Copy for std::fmt::Alignment
impl Copy for ErrorKind
impl Copy for SeekFrom
impl Copy for IpAddr
impl Copy for Ipv6MulticastScope
impl Copy for Shutdown
impl Copy for SocketAddr
impl Copy for FpCategory
impl Copy for BacktraceStyle
impl Copy for Which
impl Copy for SearchStep
impl Copy for std::sync::atomic::Ordering
impl Copy for RecvTimeoutError
impl Copy for TryRecvError
impl Copy for bool
impl Copy for char
impl Copy for f32
impl Copy for f64
impl Copy for i8
impl Copy for i16
impl Copy for i32
impl Copy for i64
impl Copy for i128
impl Copy for isize
impl Copy for !
impl Copy for u8
impl Copy for u16
impl Copy for u32
impl Copy for u64
impl Copy for u128
impl Copy for ()
impl Copy for usize
impl Copy for CpuidResult
impl Copy for __m128
impl Copy for __m128bh
impl Copy for __m128d
impl Copy for __m128i
impl Copy for __m256
impl Copy for __m256bh
impl Copy for __m256d
impl Copy for __m256i
impl Copy for __m512
impl Copy for __m512bh
impl Copy for __m512d
impl Copy for __m512i
impl Copy for TimSortRun
impl Copy for AllocError
impl Copy for Global
impl Copy for Layout
impl Copy for System
impl Copy for TypeId
impl Copy for TryFromSliceError
impl Copy for CharTryFromError
impl Copy for TryFromCharError
impl Copy for Error
impl Copy for FileTimes
impl Copy for FileType
impl Copy for Empty
impl Copy for Sink
impl Copy for Assume
impl Copy for Ipv4Addr
impl Copy for Ipv6Addr
impl Copy for SocketAddrV4
impl Copy for SocketAddrV6
impl Copy for NonZeroI8
impl Copy for NonZeroI16
impl Copy for NonZeroI32
impl Copy for NonZeroI64
impl Copy for NonZeroI128
impl Copy for NonZeroIsize
impl Copy for NonZeroU8
impl Copy for NonZeroU16
impl Copy for NonZeroU32
impl Copy for NonZeroU64
impl Copy for NonZeroU128
impl Copy for NonZeroUsize
impl Copy for TryFromIntError
impl Copy for RangeFull
impl Copy for UCred
impl Copy for ExitCode
impl Copy for ExitStatus
impl Copy for ExitStatusError
impl Copy for std::ptr::Alignment
impl Copy for Utf8Error
impl Copy for RecvError
impl Copy for WaitTimeoutResult
impl Copy for RawWakerVTable
impl Copy for AccessError
impl Copy for ThreadId
impl Copy for Duration
impl Copy for Instant
impl Copy for SystemTime
impl Copy for PhantomPinned
impl<'a> Copy for Component<'a>
impl<'a> Copy for Prefix<'a>
impl<'a> Copy for Arguments<'a>
impl<'a> Copy for IoSlice<'a>
impl<'a> Copy for Location<'a>
impl<'a> Copy for Ancestors<'a>
impl<'a> Copy for PrefixComponent<'a>
impl<'a, T, const N: usize> Copy for ArrayWindows<'a, T, N>where T: Copy + 'a,
impl<'fd> Copy for BorrowedFd<'fd>
impl<'handle> Copy for BorrowedHandle<'handle>
impl<'socket> Copy for BorrowedSocket<'socket>
impl<B, C> Copy for ControlFlow<B, C>where B: Copy, C: Copy,
impl<Dyn> Copy for DynMetadata<Dyn>where Dyn: ?Sized,
impl<F> Copy for RepeatWith<F>where F: Copy,
impl<Idx> Copy for RangeTo<Idx>where Idx: Copy,
impl<Idx> Copy for RangeToInclusive<Idx>where Idx: Copy,
impl<P> Copy for Pin<P>where P: Copy,
impl<Ret, T> Copy for fn (T₁, T₂, …, Tₙ) -> Ret
这个 trait 是在具有任意数量参数的函数指针上实现的。
impl<T> Copy for Bound<T>where T: Copy,
impl<T> Copy for Option<T>where T: Copy,
impl<T> Copy for Poll<T>where T: Copy,
impl<T> Copy for *const Twhere T: ?Sized,
impl<T> Copy for *mut Twhere T: ?Sized,
impl<T> Copy for &Twhere T: ?Sized,
共享的引用可以复制,但是可变引用 不能!
impl<T> Copy for Reverse<T>where T: Copy,
impl<T> Copy for Discriminant<T>
impl<T> Copy for ManuallyDrop<T>where T: Copy + ?Sized,
impl<T> Copy for Saturating<T>where T: Copy,
impl<T> Copy for Wrapping<T>where T: Copy,
impl<T> Copy for NonNull<T>where T: ?Sized,
impl<T> Copy for PhantomData<T>where T: ?Sized,
impl<T> Copy for MaybeUninit<T>where T: Copy,
impl<T, E> Copy for Result<T, E>where T: Copy, E: Copy,
impl<T, const LANES: usize> Copy for Mask<T, LANES>where T: MaskElement, LaneCount<LANES>: SupportedLaneCount,
impl<T, const N: usize> Copy for [T; N]where T: Copy,
impl<T, const N: usize> Copy for Simd<T, N>where LaneCount<N>: SupportedLaneCount, T: SimdElement,
impl<T: Copy> Copy for TrySendError<T>
impl<T: Copy> Copy for (T₁, T₂, …, Tₙ)
这个 trait 在任意长度的元组上实现。