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::opsstd::cmp 中的 trait 用于重载运算符索引表达式调用表达式

DerefDerefMut

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

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

SendSyncUnpinUnwindSafeRefUnwindSafe trait 是自动 trait。自动 trait 具有特殊属性。

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

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

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