特殊类型和特征
Rust 编译器识别标准库中存在的某些类型和特征。本章记录了这些类型和特征的特殊功能。
Box<T>
Box<T>
有一些 Rust 目前不允许用户定义类型的特殊功能。
Box<T>
的解引用运算符会生成一个可以移动的位置。这意味着*
运算符和Box<T>
的析构函数是内置于语言中的。- 方法可以将
Box<Self>
作为接收者。 - 可以在与
T
相同的包中为Box<T>
实现特征,而孤儿规则阻止了其他泛型类型的这种行为。
Rc<T>
Arc<T>
Pin<P>
UnsafeCell<T>
std::cell::UnsafeCell<T>
用于内部可变性。它确保编译器不会执行对此类类型不正确的优化。它还确保具有内部可变性类型的static
项不会放置在标记为只读的内存中。
PhantomData<T>
std::marker::PhantomData<T>
是一种零大小、最小对齐的类型,出于方差、丢弃检查和自动特征的目的,它被认为拥有一个 T
。
运算符特征
std::ops
和 std::cmp
中的特征用于重载运算符、索引表达式和调用表达式。
Deref
和 DerefMut
除了重载一元 *
运算符外,Deref
和 DerefMut
还用于方法解析和解引用强制转换。
Drop
Drop
特征提供了一个析构函数,每当要销毁此类型的某个值时就会运行该函数。
Copy
Copy
特征会更改实现它的类型的语义。类型实现 Copy
的值在赋值时会被复制而不是移动。
Copy
只能为不实现 Drop
且其字段均为 Copy
的类型实现。对于枚举,这意味着所有变体的 所有字段都必须是 Copy
。对于联合体,这意味着所有变体都必须是 Copy
。
编译器为以下类型实现了 Copy
Clone
Clone
特征是 Copy
的超特征,因此它也需要编译器生成的实现。编译器为以下类型实现了它
Send
Send
特征表示将此类型的值从一个线程发送到另一个线程是安全的。
Sync
Sync
特征表示在多个线程之间共享此类型的值是安全的。必须为不可变static
项中使用的所有类型实现此特征。
终止
Termination
特征指示主函数和测试函数的可接受返回类型。
自动特征
Send
、Sync
、Unpin
、UnwindSafe
和 RefUnwindSafe
特征是_自动特征_。自动特征具有特殊属性。
如果未为给定类型的自动特征写出显式实现或否定实现,则编译器会根据以下规则自动实现它
- 如果
T
实现了该特征,则&T
、&mut T
、*const T
、*mut T
、[T; n]
和[T]
也实现该特征。 - 函数项类型和函数指针自动实现该特征。
- 如果结构体、枚举、联合体和元组的所有字段都实现了该特征,则它们也实现该特征。
- 如果闭包的所有捕获的类型都实现了该特征,则该闭包也实现该特征。通过共享引用捕获
T
并通过值捕获U
的闭包实现&T
和U
都实现的任何自动特征。
对于泛型类型(将上述内置类型计为 T
上的泛型),如果泛型实现可用,则编译器不会为可以使用该实现但未满足必要特征边界的类型自动实现它。例如,标准库为所有 &T
实现 Send
,其中 T
是 Sync
;这意味着如果 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
边界来放宽。