Ownership and Borrowing
Introduction to Ownership
Ownership is Rust’s most unique feature and has deep implications for how the language works. It’s what enables Rust to make memory safety guarantees without needing a garbage collector.
The Stack and the Heap
In Rust, data can be stored in two places:
The Stack
- Fixed size
- Fast access
- Last-in, first-out
- All data must have a known, fixed size
The Heap
- Dynamic size
- Slower access
- Memory is allocated at runtime
- Returns a pointer to that location
Ownership Rules
- Each value has a variable that’s its “owner”
- There can only be one owner at a time
- When the owner goes out of scope, the value will be dropped
Variable Scope
{ // s is not valid here let s = String::from("hello"); // s is valid from this point forward // do stuff with s} // this scope is now over, and s is no longer valid
Memory and Allocation
String Type
let s = String::from("hello");
Move
let s1 = String::from("hello");let s2 = s1; // s1's value moves to s2// println!("{}", s1); // This would cause an error
Clone
let s1 = String::from("hello");let s2 = s1.clone(); // Deep copyprintln!("{}", s1); // This is fine
Ownership and Functions
fn main() { let s = String::from("hello"); takes_ownership(s); // s's value moves into the function // println!("{}", s); // This would cause an error}
fn takes_ownership(some_string: String) { println!("{}", some_string);} // some_string goes out of scope and is dropped
Return Values and Scope
fn main() { let s1 = gives_ownership(); let s2 = String::from("hello"); let s3 = takes_and_gives_back(s2);}
fn gives_ownership() -> String { let some_string = String::from("hello"); some_string}
fn takes_and_gives_back(a_string: String) -> String { a_string}
Comparing to JavaScript
JavaScript uses garbage collection:
let s1 = "hello";let s2 = s1; // s1 is still validconsole.log(s1); // "hello"
Conclusion
Ownership is a fundamental concept in Rust that enables memory safety without garbage collection.