Конструкторы

Есть только один способ создать экземпляр пользовательского типа: дать ему имя, и инициализировать сразу все его поля:


#![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)?