The stack, the heap, and pointers
The stack, the heap, and pointers are very important in Rust.
The stack and the heap are two places to keep memory in computers. The important differences are:
- The stack is very fast, but the heap is not so fast. It's not super slow either, but the stack is always faster. But you can't just use the stack all the time, because:
- Rust needs to know the size of a variable at compile time. So simple variables like
i32
go on the stack, because we know their exact size. You always know that ani32
is going to be 4 bytes, because 32 bits = 4 bytes. Soi32
can always go on the stack. - But some types don't know the size at compile time. But the stack needs to know the exact size. So what do you do? First you put the data in the heap, because the heap can have any size of data. And then to find it a pointer goes on the stack. This is fine because we always know the size of a pointer. So then the computer first goes to the stack, reads the pointer, and follows it to the heap where the data is.
Pointers sound complicated, but they are easy. Pointers are like a table of contents in a book. Imagine this book:
MY BOOK
TABLE OF CONTENTS
Chapter Page
Chapter 1: My life 1
Chapter 2: My cat 15
Chapter 3: My job 23
Chapter 4: My family 30
Chapter 5: Future plans 43
So this is like five pointers. You can read them and find the information they are talking about. Where is the chapter "My life"? It's on page 1 (it points to page 1). Where is the chapter "My job?" It's on page 23.
The pointer you usually see in Rust is called a reference. This is the important part to know: a reference points to the memory of another value. A reference means you borrow the value, but you don't own it. It's the same as our book: the table of contents doesn't own the information. It's the chapters that own the information. In Rust, references have a &
in front of them. So:
let my_variable = 8
makes a regular variable, butlet my_reference = &my_variable
makes a reference.
You read my_reference = &my_variable
like this: "my_reference is a reference to my_variable". Or: "my_reference refers to my_variable".
This means that my_reference
is only looking at the data of my_variable
. my_variable
still owns its data.
You can also have a reference to a reference, or any number of references.
fn main() { let my_number = 15; // This is an i32 let single_reference = &my_number; // This is a &i32 let double_reference = &single_reference; // This is a &&i32 let five_references = &&&&&my_number; // This is a &&&&&i32 }
These are all different types, just in the same way that "a friend of a friend" is different from "a friend".