构造函数

只有一种方法可以创建用户定义类型的实例:命名它,并立即初始化其所有字段。

#![allow(unused)]
fn main() {
struct Foo {
    a: u8,
    b: u32,
    c: bool,
}

enum Bar {
    X(u32),
    Y(bool),
}

struct Unit;

let foo = Foo { a: 0, b: 1, c: false };
let bar = Bar::X(0);
let empty = Unit;
}

就是这样。创建类型实例的任何其他方法都只是调用一个完全普通的函数,该函数执行一些操作并最终归结为“唯一真正的构造函数”。

与 C++ 不同,Rust 没有附带大量内置的构造函数类型。没有复制构造函数、默认构造函数、赋值构造函数、移动构造函数或任何其他构造函数。原因多种多样,但主要归结为 Rust 的“显式”哲学。

移动构造函数在 Rust 中毫无意义,因为我们不允许类型“关心”它们在内存中的位置。每种类型都必须准备好被盲目地内存复制到内存中的其他位置。这意味着纯粹的基于堆栈但仍然可移动的侵入式链表根本不会(安全地)发生在 Rust 中。

赋值构造函数和复制构造函数同样不存在,因为移动语义是 Rust 中唯一的语义。最多 x = y 只是将 y 的位移动到 x 变量中。Rust 确实提供了两种工具来提供 C++ 的面向复制的语义:CopyClone。Clone 在道德上等同于复制构造函数,但它永远不会被隐式调用。您必须在要克隆的元素上显式调用 clone。Copy 是 Clone 的一种特殊情况,其实现只是“复制位”。Copy 类型在移动时会被隐式克隆,但由于 Copy 的定义,这仅仅意味着不将旧副本视为未初始化的——一个空操作。

虽然 Rust 提供了一个 Default trait 来指定在道德上等同于默认构造函数的内容,但很少使用此 trait。这是因为变量不会被隐式初始化。Default 基本上只对泛型编程有用。在具体上下文中,类型将为任何类型的“默认”构造函数提供静态 new 方法。这与其他语言中的 new 无关,也没有特殊含义。它只是一个命名约定。

TODO:谈谈“就地 new”?