Конструкторы
Есть только один способ создать экземпляр пользовательского типа: дать ему имя, и инициализировать сразу все его поля:
#![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 не поставляется с убийственным набором конструкторов. В нем нет Copy, Default, Assignment, Move или ещё каких-либо конструкторов. Этому множество причин, но основной является философия Rust - быть явным.
Конструкторы перемещения бессмысленны в Rust, потому что мы не позволяем типам "заботиться" о своём расположении в памяти. Каждый тип должен быть готов быть скопированным в другое место в памяти. Это означает, что чистые на-стеке-но-всё-ещё-перемещаемые встроенные связные списки (intrusive linked lists) просто невозможно встретить в Rust (безопасном).
Конструкторы присваивания и копирования не существуют, потому что семантика перемещения - это единственная семантика в Rust. В большинстве случаев x = y
просто перемещает биты y в переменную x. Rust даёт две возможности для предоставления copy-ориентированной семантики C++: Copy
и Clone
. Clone
- это наш духовный эквивалент конструктора Copy
, но он никогда не вызовется неявно. Вам нужно явно вызвать clone
у элемента, который вы хотите клонировать. Copy - особый случай Clone, у которого реализацией является просто "скопируй биты". Типы Copy неявно клонируются во время перемещения, но, исходя из определения Copy, это означает просто не считать старую копию неинициализированной - то есть, это пустая операция.
Хоть Rust и предоставляет типаж Default
для определения духовного эквивалента конструктора по умолчанию, его очень редко используют. Все из-за того, что переменные не инициализируются неявно. Default в основном полезен только для обобщённого программирования. В конкретном контексте, тип предоставит статический метод new
для любого типа конструкторов "по умолчанию". Здесь нет связи с new
из других языков, и особого смысла это слово тоже не несёт. Это просто соглашение именования.
TODO: рассказать о "размещающем new" (placement new)?