Rust 中的标记特征是什么?

mas*_*cai 5 traits rust

我正在学习 Rust,想深入研究标记特征。官方文档的定义对我来说不清楚: https: //doc.rust-lang.org/std/marker/index.html

定义:

代表类型基本属性的原始特征和类型。Rust 类型可以根据其内在属性以各种有用的方式进行分类。这些分类被表示为特征。

  1. 为什么我们定义一组特殊的特征并将其称为“标记特征”?这些特征有何特别之处?

  2. 我是否正确理解所有这些特征都有默认实现,并且我们可以在不实现的情况下为自定义结构派生这些特征?

您能举例回答吗?

Ale*_*uze 10

标记特征用于将类型标记为具有某些属性。它们通常没有任何关联的类型和方法,用于告诉编译器有关类型的某些属性。请注意,其中一些特征是自动特征,这意味着编译器将自动为类型实现它们,如果它认为这样做是安全的(您仍然可以手动实现它们,但可能需要unsafe关键字)。

目前(rustc 1.70.0)模块中有 5 个稳定特征std::marker。它们具有以下含义。如果类型T实现:

  • Copy这意味着它可以Clone通过使用按位复制来实现
  • Send这意味着类型的值T可以跨线程边界发送
  • Sync这意味着类型的值T可以在线程之间共享(&TSend
  • Sized意味着类型的大小T在编译时已知
  • Unpin意味着类型的值在固定T后可以移动

上述SendSyncUnpin是自动特征。std::panic模块中还有两个更稳定的 auto 特征。

回答您的问题。

为什么我们定义一组特殊的特征并将其称为“标记特征”?这些特征有何特别之处?

我们将这些特征称为“标记”,以区分接口的实现和向编译器提供有关类型属性的信息,这两者都是通过特征在 Rust 中完成的。然而,它们并没有什么特别之处。这些都是与其他特征一样的正常特征。这只是我们人类的语义名称。

我是否正确理解所有这些特征都有默认实现,并且我们可以在不实现的情况下为自定义结构派生这些特征?

严格来说,它们没有默认实现,因为通过这个术语,我们理解特征方法的默认实现,该方法与实现给定特征的所有类型共享,并且可以被它们覆盖。例如std::io::Write::write_all

然而,由于它们没有任何方法,我们可以简单地为我们的类型实现它们,只需说该类型实现了此特征。例如,我们可以Copy像这样实现我们的类型(我们将使用它#[derive(Clone)],这样我们就不必手动实现它,因为Clone是 的超级特征Copy

#[derive(Clone)]
struct Foo {
    a: i32,
    b: f32,
    c: bool,
}

impl Copy for Foo {}
Run Code Online (Sandbox Code Playgroud)

您还可以实现编译器未自动实现的自动特征。例如,任何包含原始指针的类型都会自动标记为!Send负实现是编译器使用的不稳定功能)。但是,如果在线程之间发送此类类型是安全的Send,您可以显式实现它(请注意,您必须使用unsafe关键字,因为错误的实现Send可能会导致未定义的行为:

struct Bar {
    ptr: *const (),
}

unsafe impl Send for Bar {}
Run Code Online (Sandbox Code Playgroud)

然而,一旦异常是 Trait Sized,它只能由编译器实现。尝试手动实现它会导致E0322错误。