原文链接:https://doc.rust-lang.org/nomicon/constructors.html
构造函数
创建一个自定义类型的实例的方法只有一种:先命名,然后一次性初始化它的所有成员:
#![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没什么用,因为我们并不需要让类型关心它们在内存上的位置。没一个类型都有可能随时被memcopy到内存中其他的位置上。这也意味和那种存储于栈上却依然可以移动的侵入式链表在Rust中是不可能(安全地)存在的。
复制和拷贝构造函数也是不存在的,因为Rust中的类型有且仅有移动语义。x = y
只是将y
的字节移动到x
的变量中。Rust倒是提供了两种和C++中的copy语义相似的功能:Copy
和Clone
。Clone
很像是拷贝构造函数,但是它不会被隐式调用。你必须在需要复制的元素上显式调用clone
方法、Copy
是Clone
的一个特例,它的实现只会拷贝字节码。Copy类型在移动的时候会隐式地复制,但是因为Copy的定义,这个方法只是不把旧的值设置为未初始化而已——其实是一个no-op。
虽然Rust确实有一个Default
trait,它与默认构造函数很相似,但是这个trait极少被用到。这是因为变量不会被隐式初始化。Default
一般只有在泛型编程中才有用。而具体的类型会提供一个new
静态方法来实现默认构造函数的功能。这个和其他语言中的new
关键字没什么关系,也没有什么特殊的含义。它仅仅是一个明明习惯而已。
TODO:介绍“placement new”?