¹mostly
fn foo() { // Creates a Vec object. // Gives ownership of the Vec object to v1. let mut v1 = vec![1, 2, 3]; v1.pop(); v1.push(4); // At the end of the scope, v1 goes out of scope. // v1 still owns the Vec object, so it can be cleaned up.}
So here are the basics.
let v1 = vec![1, 2, 3];// Ownership of the Vec object moves to v2.let v2 = v1;println!("{}", v1[2]); // error: use of moved value `v1`
let v2 = v1;
v2
, and declare v1
invalid.println!("{}", v1[2]);
v1
is no longer a valid variable binding, so this is an error.Here's another example:
std::move
.std::mem::replace
in Rust to provide
advanced ownership management.fn vector_length(v: Vec<i32>) -> Vec<i32> { // Do whatever here, // then return ownership of `v` back to the caller}
let v = vec![1, 2, 3];// v_ref is a reference to v.let v_ref = &v;// use v_ref to access the data in the vector v.assert_eq!(v[1], v_ref[1]);
let v = vec![1, 2, 3];// v_ref is a reference to v.let v_ref = &v;// Moving ownership to v_new would invalidate v_ref.// error: cannot move out of `v` because it is borrowedlet v_new = v;
/// `length` only needs `vector` temporarily, so it is borrowed.fn length(vec_ref: &Vec<i32>) -> usize { // vec_ref is auto-dereferenced when you call methods on it. vec_ref.len() // you can also explicitly dereference. // (*vec_ref).len()}fn main() { let vector = vec![]; length(&vector); println!("{:?}", vector); // this is fine}
length
: vec_ref
is passed by reference, so it's now an &Vec<i32>
.length
)./// `push` needs to modify `vector` so it is borrowed mutably.fn push(vec_ref: &mut Vec<i32>, x: i32) { vec_ref.push(x);}fn main() { let mut vector: Vec<i32> = vec![]; let vector_ref: &mut Vec<i32> = &mut vector; push(vector_ref, 4);}
&mut vec_ref
.vec_ref
is a reference to a mutable Vec
.&mut Vec<i32>
, not &Vec<i32>
./// `push` needs to modify `vector` so it is borrowed mutably.fn push2(vec_ref: &mut Vec<i32>, x: i32) { // error: cannot move out of borrowed content. let vector = *vec_ref; vector.push(x);}fn main() { let mut vector = vec![]; push2(&mut vector, 4);}
vec_ref
into a variable binding because that
would change the ownership of the data./// `length` only needs `vector` temporarily, so it is borrowed.fn length(vec_ref: &&Vec<i32>) -> usize { // vec_ref is auto-dereferenced when you call methods on it. vec_ref.len()}fn main() { let vector = vec![]; length(&&&&&&&&&&&&vector);}
let mut a = 5;let ref_a = &mut a;*ref_a = 4;println!("{}", *ref_a + 4);// ==> 8
ref
let mut vector = vec![0];{ // These are equivalent let ref1 = &vector; let ref ref2 = vector; assert_eq!(ref1, ref2);}let ref mut ref3 = vector;ref3.push(1);
ref
can be applied to make the variable a reference to the assigned value.ref mut
.match
statements when destructuring patterns.ref
let mut vectors = (vec![0], vec![1]);match vectors { (ref v1, ref mut v2) => { v1.len(); v2.push(2); }}
ref
and ref mut
when binding variables inside match statements.Copy
TypesCopy
that signifies that a type may be
copied instead whenever it would be moved.Copy
(i32
, f64
, char
, bool
, etc.)Copy
(e.g. Vec
, String
).let x: i32 = 12;let y = x; // `i32` is `Copy`, so it's not moved :Dprintln!("x still works: {}, and so does y: {}", x, y);
¹ Like a Java interface or Haskell typeclass
This is why we've been using Vectors as examples in this slide set.
Learn these rules, and they will serve you well.
&T
).&mut T
) (not both).ConcurrentModificationException
(at runtime!)let mut vs = vec![1,2,3,4];for v in &vs { vs.pop(); // ERROR: cannot borrow `vs` as mutable because // it is also borrowed as immutable}
pop
needs to borrow vs
as mutable in order to modify the data.vs
is being borrowed as immutable by the loop!let y: &i32;{ let x = 5; y = &x; // error: `x` does not live long enough}println!("{}", *y);
error: `x` does not live long enoughnote: reference must be valid for the block suffix following statement 0 at 1:16...but borrowed value is only valid for the block suffix following statement 0 at 4:18
As a side note, this technique of creating a block to limit the scope of a variable (in this case x) is pretty useful.
Vec
s in three different ways:let mut vs = vec![0,1,2,3,4,5,6];// Borrow immutablyfor v in &vs { // Can also write `for v in vs.iter()` println!("I'm borrowing {}.", v);}// Borrow mutablyfor v in &mut vs { // Can also write `for v in vs.iter_mut()` *v = *v + 1; println!("I'm mutably borrowing {}.", v);}// Take ownership of the whole vectorfor v in vs { // Can also write `for v in vs.into_iter()` println!("I now own {}! AHAHAHAHA!", v);}// `vs` is no longer valid
¹mostly
Keyboard shortcuts
↑, ←, Pg Up, k | Go to previous slide |
↓, →, Pg Dn, Space, j | Go to next slide |
Home | Go to first slide |
End | Go to last slide |
b / m / f | Toggle blackout / mirrored / fullscreen mode |
c | Clone slideshow |
p | Toggle presenter mode |
t | Restart the presentation timer |
?, h | Toggle this help |
Esc | Back to slideshow |