mirror of https://github.com/rust-lang/nomicon
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
60 lines
2.3 KiB
60 lines
2.3 KiB
8 years ago
|
# Constructors
|
||
10 years ago
|
|
||
10 years ago
|
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 {
|
||
10 years ago
|
a: u8,
|
||
|
b: u32,
|
||
|
c: bool,
|
||
10 years ago
|
}
|
||
|
|
||
|
enum Bar {
|
||
10 years ago
|
X(u32),
|
||
|
Y(bool),
|
||
10 years ago
|
}
|
||
|
|
||
10 years ago
|
struct Unit;
|
||
10 years ago
|
|
||
|
let foo = Foo { a: 0, b: 1, c: false };
|
||
|
let bar = Bar::X(0);
|
||
10 years ago
|
let empty = Unit;
|
||
10 years ago
|
```
|
||
|
|
||
|
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.
|
||
|
|
||
10 years ago
|
Unlike C++, Rust does not come with a slew of built-in kinds of constructor.
|
||
10 years ago
|
There are no Copy, Default, Assignment, Move, or whatever constructors. The
|
||
10 years ago
|
reasons for this are varied, but it largely boils down to Rust's philosophy of
|
||
|
*being explicit*.
|
||
10 years ago
|
|
||
|
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
|
||
9 years ago
|
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-
|
||
10 years ago
|
oriented semantics: `Copy` and `Clone`. Clone is our moral equivalent of a copy
|
||
10 years ago
|
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
|
||
9 years ago
|
means not treating the old copy as uninitialized -- a no-op.
|
||
10 years ago
|
|
||
|
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.
|
||
10 years ago
|
|
||
|
TODO: talk about "placement new"?
|
||
|
|
||
|
[uninit]: uninitialized.html
|