| # Constructors | |
| There is exactly one way to create an instance of a user-defined type: name it, | |
| and initialize all its fields at once: | |
| ```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; | |
| ``` | |
| That's it. Every other way you make an instance of a type is just calling a | |
| totally vanilla function that does some stuff and eventually bottoms out to The | |
| One True Constructor. | |
| Unlike C++, Rust does not come with a slew of built-in kinds of constructor. | |
| There are no Copy, Default, Assignment, Move, or whatever constructors. The | |
| reasons for this are varied, but it largely boils down to Rust's philosophy of | |
| *being explicit*. | |
| Move constructors are meaningless in Rust because we don't enable types to | |
| "care" about their location in memory. Every type must be ready for it to be | |
| blindly memcopied to somewhere else in memory. This means pure on-the-stack-but- | |
| still-movable intrusive linked lists are simply not happening in Rust (safely). | |
| Assignment and copy constructors similarly don't exist because move semantics | |
| are the only semantics in Rust. At most `x = y` just moves the bits of y into | |
| the x variable. Rust does provide two facilities for providing C++'s copy- | |
| oriented semantics: `Copy` and `Clone`. Clone is our moral equivalent of a copy | |
| constructor, but it's never implicitly invoked. You have to explicitly call | |
| `clone` on an element you want to be cloned. Copy is a special case of Clone | |
| where the implementation is just "copy the bits". Copy types *are* implicitly | |
| cloned whenever they're moved, but because of the definition of Copy this just | |
| means not treating the old copy as uninitialized -- a no-op. | |
| While Rust provides a `Default` trait for specifying the moral equivalent of a | |
| default constructor, it's incredibly rare for this trait to be used. This is | |
| because variables [aren't implicitly initialized][uninit]. Default is basically | |
| only useful for generic programming. In concrete contexts, a type will provide a | |
| static `new` method for any kind of "default" constructor. This has no relation | |
| to `new` in other languages and has no special meaning. It's just a naming | |
| convention. | |
| TODO: talk about "placement new"? | |
| [uninit]: uninitialized.html |