every value
has a variable
that is it's owner
;
Stacks are Last in First Out LIFO
, stacks are organized and all data to be stored on the stack must have a known fixed size. Pushing and searching data are faster in the stack. (local var, functions arguments) are stored on the stack.
Heaps are less organized, stores data without a known size at compile time or data that may change. When an item is added to the heap, you request
a memory, which then returns a pointer
to the data.
The owner is responsible for cleaning up the value's memory when it is no longer needed.
Rules of ownership.
- each value in rust has a variable called its owner
- one owner at a time
- when an owner goes out of scope, the value is drop (or memory is freed);
// value 25 is owned by num
// stack allocated
// does not change at runtime time
let num: i32 = 25;
// string "dynamic" is owned by str
// heap allocated
let mut str: String = "dynamic".to_string();
// changes at runtime
str.push_str(", world");
moves the ownership of a value from one variable to another.
// intial owner of the vector is x;
let x = vec!["peter".to_string()];
// changes the owner to y
let y = x;
// changes the owner to z
let z = y;
// does not work because the value has moved
println!("{}", x);
// does not work because the value has moved
println!("{}", y);
// works
println!("{}", z);
creates a deep copy of a value. assigning a new owner to the it. expensive too
// a is the owner of the vector
let a = vec!["peter".to_string()];
// b clones a and is the owner of the clone
let b = a.clone();
// c clones b and the owner of the clone
let c = b.clone();
some types in rust implements the copy trait
. most stack allocated primitive types implements copy.
let int1 = 5; // i32
let int2 = int1 // i32
// work! because the type i32 is a copy
println!("{} {}", int1, int2)
references allows us to make a reference to a value without taking ownership of it. ie borrowing
.
- shared: read only reference
- mutable: read + write references, however you can not have multiple active refs to the value at a time.
passing by reference allows for a value to be modified without first taking ownership of it;
let mut mutable = String::from("i am");
let non_mutable = String::from("i am not");
// works
mutable.push_str(" mut");
// fails, cannot not borrow a non mutable ref
non_mutable.push_str(" mut");