// Example 4: Ownership and references #[derive(Copy, Clone)] struct Thing { label: char, count: i32, } fn print_thing_val(x: Thing) { // (This is the same code we were looking at before.) println!("the count of {} is {}", x.label, x.count); } fn print_thing_ref(x: &Thing) { // ^~ this is a "reference type constructor" // `&T` is pronounced "(shared) reference to T" println!("the count of `{}` is {}", x.label, x.count); let Thing { label, count } = *x; println!("another way to bind (`{}` still {})", label, count); let &Thing { label, count } = x; println!("even &pat is a pattern (and `{}` still {})", label, count); } fn print_thing_box(x: Box<Thing>) { // ^~~ This is another type constructor // (One of many library-provided "smart-pointers") // `Box<T>` is pronounced "boxed T" println!("the count of {} is {}", x.label, x.count); } pub fn main() { // stack-allocated, as before let t1 = Thing { label: 'a', count: 5 }; // These two calls have the same side-effects ... print_thing_val(t1); print_thing_ref(&t1); // ... but they do their work in very diferrent ways. // *heap*-allocated Thing let t2 = Box::new(Thing { label: 'b', count: 4 }); print_thing_box(t2); // EXERCISE: Add code below here to print both `t1` and `t2` // again. Discuss. } // Box<Thing> behaves very differently from `Thing` and `&Thing`. // // A detail we've been avoiding due to something special with `Thing`. // // But it is *not* something special about `Box`; it is *Thing* that // is special; discuss. // EXERCISE: add a new function, `increment_count`, that takes a // `Thing` and adds 1 to its count field in a way that the *caller* // can observe.