fn main() { // Box points to 5 allocated on the heap let b = Box::new(5); println!("b = {}", b); }
enum List { Cons(i32, List), Nil, }
Equivalent to
use crate::List::{Cons, Nil}; fn main() { let list = Cons(1, Cons(2, Cons(3, Nil))); }
$ cargo run Compiling cons-list v0.1.0 (file:///projects/cons-list) error[E0072]: recursive type `List` has infinite size --> src/main.rs:1:1 | 1 | enum List { | ^^^^^^^^^ recursive type has infinite size 2 | Cons(i32, List), | ---- recursive without indirection | = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `List` representable error[E0391]: cycle detected when processing `List` --> src/main.rs:1:1 | 1 | enum List { | ^^^^^^^^^ | = note : ...which again requires processing `List`, completing the cycle = note : cycle used when computing dropck types for `Canonical { max_universe: U0, variables: [], value: ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing, def_id: None }, value: List } }` error: aborting due to 2 previous errors Some errors have detailed explanations: E0072, E0391. For more information about an error, try `rustc --explain E0072`. error: could not compile `cons-list`. To learn more, run the command again with --verbose.
enum List { Cons(i32, Box<List>), Nil, } use crate::List::{Cons, Nil}; fn main() { let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil)))))); }
Customise the behaviour of the deference operator *
fn main() { let x = 5; let y = &x; assert_eq!(5, x); assert_eq!(5, *y); // using the deference operator }
fn main() { let x = 5; let y = Box::new(x); assert_eq!(5, x); assert_eq!(5, *y); // using the deference operator }
struct MyBox<T>(T); impl<T> MyBox<T> { fn new(x: T) -> MyBox<T> { MyBox(x) } }
fn main() { let x = 5; let y = MyBox::new(x); assert_eq!(5, x); assert_eq!(5, *y); }
$ cargo run Compiling deref-example v0.1.0 (file:///projects/deref-example) error[E0614]: type `MyBox<{integer}>` cannot be dereferenced --> src/main.rs:14:19 | 14 | assert_eq!(5, *y); | ^^ error: aborting due to previous error For more information about this error, try `rustc --explain E0614`. error: could not compile `deref-example`. To learn more, run the command again with --verbose.
use std::ops::Deref; impl<T> Deref for MyBox<T> { type Target = T; fn deref(&self) -> &T { &self.0 } }
Converts a type that implement the deref trait into a reference to another type.
fn hello(name: &str) { println!("Hello, {}!", name); }
fn main() { let m = MyBox::new(String::from("Rust")); hello(&m); }
Use the DerefMut trait to override the * operator on mutable references.
struct CustomSmartPointer { data: String, } impl Drop for CustomSmartPointer { fn drop(&mut self) { println!("Dropping CustomSmartPointer with data `{}`!", self.data); } }
fn main() { let c = CustomSmartPointer { data: String::from("my stuff"), }; let d = CustomSmartPointer { data: String::from("other stuff"), }; println!("CustomSmartPointers created."); }
$ cargo run Compiling drop-example v0.1.0 (file:///projects/drop-example) Finished dev [unoptimized + debuginfo] target(s) in 0.60s Running `target/debug/drop-example` CustomSmartPointers created. Dropping CustomSmartPointer with data `other stuff`! Dropping CustomSmartPointer with data `my stuff`!
fn main() { let c = CustomSmartPointer { data: String::from("some data"), }; println!("CustomSmartPointer created."); c.drop(); println!("CustomSmartPointer dropped before the end of main."); }
$ cargo run Compiling drop-example v0.1.0 (file:///projects/drop-example) error[E0040]: explicit use of destructor method --> src/main.rs:16:7 | 16 | c.drop(); | ^^^^ explicit destructor calls not allowed error: aborting due to previous error
fn main() { let c = CustomSmartPointer { data: String::from("some data"), }; println!("CustomSmartPointer created."); drop(c); // std::mem::drop println!("CustomSmartPointer dropped before the end of main."); }
$ cargo run Compiling drop-example v0.1.0 (file:///projects/drop-example) Finished dev [unoptimized + debuginfo] target(s) in 0.73s Running `target/debug/drop-example` CustomSmartPointer created. Dropping CustomSmartPointer with data `some data`! CustomSmartPointer dropped before the end of main.
A single value might have multiple owners.
use crate::List::{Cons, Nil}; fn main() { let a = Cons(5, Box::new(Cons(10, Box::new(Nil)))); let b = Cons(3, Box::new(a)); let c = Cons(4, Box::new(a)); }
$ cargo run Compiling cons-list v0.1.0 (file:///projects/cons-list) error[E0382]: use of moved value: `a` --> src/main.rs:11:30 | 9 | let a = Cons(5, Box::new(Cons(10, Box::new(Nil)))); | - move occurs because `a` has type `List`, which does not implement the `Copy` trait 10 | let b = Cons(3, Box::new(a)); | - value moved here 11 | let c = Cons(4, Box::new(a)); | ^ value used here after move error: aborting due to previous error For more information about this error, try `rustc --explain E0382`. error: could not compile `cons-list`. To learn more, run the command again with --verbose.
enum List { Cons(i32, Rc<List>), Nil, } use crate::List::{Cons, Nil}; use std::rc::Rc; fn main() { let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil))))); let b = Cons(3, Rc::clone(&a)); let c = Cons(4, Rc::clone(&a)); }
fn main() { let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil))))); println!("count after creating a = {}", Rc::strong_count(&a)); let b = Cons(3, Rc::clone(&a)); println!("count after creating b = {}", Rc::strong_count(&a)); { let c = Cons(4, Rc::clone(&a)); println!("count after creating c = {}", Rc::strong_count(&a)); } println!("count after c goes out of scope = {}", Rc::strong_count(&a)); }
$ cargo run Compiling cons-list v0.1.0 (file:///projects/cons-list) Finished dev [unoptimized + debuginfo] target(s) in 0.45s Running `target/debug/cons-list` count after creating a = 1 count after creating b = 2 count after creating c = 3 count after c goes out of scope = 2