Rust 构造函数

创建一个自定义类型的实例的方法只有一种:先命名,然后一次性初始化它的所有成员:

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没什么用,因为我们并不需要让类型关心它们在内存上的位置。没一个类型都有可能随时被memcopy到内存中其他的位置上。这也意味和那种存储于栈上却依然可以移动的侵入式链表在Rust中是不可能(安全地)存在的。

复制和拷贝构造函数也是不存在的,因为Rust中的类型有且仅有移动语义。x = y只是将y的字节移动到x的变量中。Rust倒是提供了两种和C++中的copy语义相似的功能:CopyCloneClone很像是拷贝构造函数,但是它不会被隐式调用。你必须在需要复制的元素上显式调用clone方法、CopyClone的一个特例,它的实现只会拷贝字节码。Copy类型在移动的时候会隐式地复制,但是因为Copy的定义,这个方法只是不把旧的值设置为未初始化而已——其实是一个no-op。

虽然Rust确实有一个Default trait,它与默认构造函数很相似,但是这个trait极少被用到。这是因为变量不会被隐式初始化。Default一般只有在泛型编程中才有用。而具体的类型会提供一个new静态方法来实现默认构造函数的功能。这个和其他语言中的new关键字没什么关系,也没有什么特殊的含义。它仅仅是一个命名习惯而已。

TODO:介绍“placement new”?

下一章:Rust 析构函数

Rust通过Drop trait提供了一个成熟的自动析构函数,包含了这个方法:fn drop(&mut self);这个方法给了类型一个彻底完成工作的机会。drop执行之后,Rust会递归地销毁self的所有成员 ...