So Rust has a steep learning curve. I keep coming back to the ownership documentation to clear a few things up. Here are some of the things I might find useful for later.
Stack v/s Heap
Stack
- Stack allows only a fixed size data
- Stack is faster since it just has to go to the next consecutive pointer position (which increments after a push)
Heap
- Requires the heap to locate space for data (which can be variable)
- Pointer has to move around since it’s not consecutive given that data can be of different size
- Processor slows down since it has to follow the pointer
The String
type
- Gets allocated - i.e. stored on the heap.
- Can use the
from
function to create a String from a string literal
let s = String::from("my literal");
- Literals are cool, they’re hard coded, need only a set amount of space and the compiler doesn’t have to worry about allocating more.
- But for stuff that’s mutable we don’t know how much is going to be required at compile time
- Rust cleans up after the variable leaves scope.
let s1 = String::from("my literal");
let s2 = s1;
s1
is now invalidated. Can’t have two pointers pointing to the same location.s2
now has ownership. This is called move also knows as shallow copy.- We can do a hard copy too, it’s called
clone
it copies data. It creates a copy on the heap which means it’s expensive.
let s1 = String::from("something);
let s2 = s1.clone();
Other pre declared types
let x = 10;
let y = x;
- Here
x
is stored on the stack, not the heap because there is a pre determined data type size that is either inferred by the compiler or the programmer actually declares x
doesn’t lose ownership here,y
is a hard copy ofx
because it’s not on the heap. It’s on the stack.
Copy & Drop trait
- A type with a
Copy
trait will allow an older variable is still usable after assignment. - However a
Copy
trait is not allowd to be placed on a type that also implements aDrop
trait. - Types like
bool
,i32
etc. implementCopy
and are put on the stack but things likeString
aren’t
Function calls and ownership
- Everytime you pass a variable to a function, the ownership changes
- For things like
String
the variable can’t be used after it’s passed to the function call - For things like
i32
the variable can be used after it’s been passed - Example taken from the documentation
fn main() {
let s = String::from("hello"); // s comes into scope
takes_ownership(s); // s's value moves into the function...
// ... and so is no longer valid here
let x = 5; // x comes into scope
makes_copy(x); // x would move into the function,
// but i32 is Copy, so it’s okay to still
// use x afterward
println!("{}", x); // this will be okay
} // Here, x goes out of scope, then s. But because s's value was moved, nothing
// special happens.
fn takes_ownership(some_string: String) { // some_string comes into scope
println!("{}", some_string);
} // Here, some_string goes out of scope and `drop` is called. The backing
// memory is freed.
fn makes_copy(some_integer: i32) { // some_integer comes into scope
println!("{}", some_integer);
} // Here, some_integer goes out of scope. Nothing special happens.