Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

特殊类型和 trait

标准库中的某些类型和 trait 为 Rust 编译器所知。本章记录了这些类型和 trait 的特殊特性。

Box<T>

Box<T> 具有一些 Rust 目前不允许用户定义类型使用的特殊特性。

  • Box<T> 的解引用运算符产生一个可以移出的位置。这意味着 * 运算符和 Box<T> 的析构函数是语言内置的。
  • 方法可以将 Box<Self> 作为接收者(receiver)。
  • 可以在与 T 相同的 crate 中为 Box<T> 实现 trait,而孤儿规则禁止其他泛型类型这样做。

Rc<T>

方法可以将 Rc<Self> 作为接收者。

Arc<T>

方法可以将 Arc<Self> 作为接收者。

Pin<P>

方法可以将 Pin<P> 作为接收者。

UnsafeCell<T>

std::cell::UnsafeCell<T> 用于内部可变性。它确保编译器不会对此类类型执行不正确的优化。

它还确保具有内部可变性类型的 static 项不会被放置在标记为只读的内存中。

PhantomData<T>

std::marker::PhantomData<T> 是一个零大小、最小对齐的类型,对于变型、丢弃检查和自动 trait的目的,它被认为是拥有一个 T。

运算符 trait

std::ops 和 std::cmp 中的 trait 用于重载运算符、索引表达式和调用表达式。

Deref 和 DerefMut

除了重载一元 * 运算符外,Deref 和 DerefMut 还用于方法解析和解引用强制转换。

Drop

Drop trait 提供了一个析构函数,在此类型的值将被销毁时运行。

Copy

Copy trait 改变了实现它的类型的语义。

类型实现 Copy 的值在赋值时被复制而不是移动。

Copy 只能为不实现 Drop 且其所有字段都是 Copy 的类型实现。对于枚举,这意味着所有变体的所有字段都必须是 Copy。对于联合体,这意味着所有变体都必须是 Copy。

编译器为以下类型实现 Copy:

  • 不捕获值或仅捕获 Copy 类型值的闭包

Clone

Clone trait 是 Copy 的超 trait,因此它也需要编译器生成的实现。

编译器为以下类型实现它:

  • 具有内置 Copy 实现的类型(见上文)
  • 仅捕获 Clone 类型值或不从环境捕获值的闭包

Send

Send trait 表示此类型的值可以安全地从一个线程发送到另一个线程。

Sync

Sync trait 表示此类型的值可以安全地在多个线程之间共享。

所有在不可变 static 项中使用的类型都必须实现此 trait。

Termination

Termination trait 指示 main 函数和测试函数可接受的返回类型。

自动 trait

Send、Sync、Unpin、UnwindSafe 和 RefUnwindSafe trait 是自动 trait。自动 trait 具有特殊属性。

如果没有为给定类型的自动 trait 编写显式实现或否定实现,则编译器根据以下规则自动实现它:

  • 如果 T 实现了该 trait,则 &T、&mut T、*const T、*mut T、[T; n] 和 [T] 也实现该 trait。
  • 函数项类型和函数指针自动实现该 trait。
  • 如果结构体、枚举、联合体和元组的所有字段都实现了该 trait,则它们也实现该 trait。
  • 如果闭包的所有捕获的类型都实现了该 trait,则闭包也实现该 trait。通过共享引用捕获 T 和通过值捕获 U 的闭包实现了 &T 和 U 都实现的任何自动 trait。

对于泛型类型(将上述内置类型视为对 T 泛型),如果存在泛型实现,则编译器不会自动为那些本可以使用该实现但不满足所需 trait 约束的类型实现它。例如,标准库为所有 T 是 Sync 的 &T 实现了 Send;这意味着如果 T 是 Send 但不是 Sync,编译器将不会为 &T 实现 Send。

自动 trait 也可以有否定实现,在标准库文档中显示为 impl !AutoTrait for T,覆盖自动实现。例如 *mut T 具有 Send 的否定实现,因此 *mut T 不是 Send,即使 T 是。目前没有稳定方式来指定额外的否定实现;它们仅存在于标准库中。

自动 trait 可以作为附加约束添加到任何 trait 对象中,即使通常只允许一个 trait。例如,Box<dyn Debug + Send + UnwindSafe> 是有效类型。

Sized

Sized trait 表示此类型的大小在编译时已知;也就是说,它不是动态大小类型。

类型参数(trait 中的 Self 除外)默认是 Sized,关联类型也是如此。

Sized 始终由编译器自动实现,而不是通过实现项。

这些隐式 Sized 约束可以通过使用特殊的 ?Sized 约束来放宽。