Files
Learning/Rust_Concepts/src/borrowing.rs
2026-04-04 08:00:20 -07:00

129 lines
6.4 KiB
Rust
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* Rust Concepts: https://sociocyber.site/rust_concepts_v2.html
Concept: Borrowing (shared &)
Usage: read a value, without holding it.
---
We call the action of creating a reference borrowing.
As in real life, if a person owns something,
you can borrow it from them. When youre done,
you have to give it back. You dont own it.
Ampersands '&' represent references,
and they allow you to refer to some value
without taking ownership of it.
& to indicate of the parameter X is a reference.
---
Owner1 in this context means who (stack frame) hold a data in heap [MEM area]
Value can be shared to someone.
& (reference) means = i want share this variable-value to someone
We can reference to a variable for get,read his value.
One variable can have many who want get his value.
MANY readers and ONE value.
Many & (references) to somethings.
(many &refs allowed simultaneously)
We can NOT change reference.
We can NOT change value when want to read this.
& (reference) = not changeble, only readable
&owner1 means = reference to a variable for get his value.
STACK (and his frames) [CPU] HEAP [MEM]
────────────────────────────────── ──────────────────────
frame: main() ┌────────────────────┐
┌──────────────────────────────┐ │ "Borrowing Value" │
│ owner1 : String │ owns │ 15 bytes, UTF-8 │
│ ┌──────────────────────────┐ │ ─────────► │ [B][o][r][r][o]... │
│ │ ptr │ │ └────────────────────┘
│ │ len = 15 │ │
│ │ cap = 15 │ │
│ └──────────────────────────┘ │
└──────────────────────────────┘
frame: print_len( &owner1 )
┌──────────────────────────────┐
│ s : &String (borrow) │
│ ┌──────────────────────────┐ │
│ │ ptr ──► owner1 │ │ (read-only, no copy)
│ └──────────────────────────┘ │
└──────────────────────────────┘
└─► borrow ends when print_len() returns
frame: println!("{}", owner1)
┌──────────────────────────────┐
│ owner1 still valid │
│ println! auto-borrows &owner1│
│ no & needed in code │
└──────────────────────────────┘
*/
/* Arguments in functions creates a new stack frame
with pointer2 --> pointer1 --> Heap first address of "v a l u e"
Like it: add_word(arg1: &String)
&arg1 - new ptr -> ptr -> value
*/
fn print_len(string: &String) { // borrows
println!("{}", string.len()); // Read reference (de-reference for get value) ptr2(&owner1) => get ptr1 (owner1) => read heap
}
fn main() {
let owner1 = String::from("Borrowing Value");
// change_value(&owner1); // Not allowed! We can't change value only READ.
print_len(&owner1); // borrowing, not ownership. Not change address in stack-slot for ptr (-> heap), make new ptr in stack (in new frame [ptr ──► owner1])
// ptr2 (reference1) -> ptr1 (owner1) -> heap ["Borrowing Value"]
// ptr2 (reference2) -> ptr1 (owner1) -> heap ["Borrowing Value"]
// ptr2 (reference3) -> ptr1 (owner1) -> heap ["Borrowing Value"]
// ptr2 (&owner1) -> ptr1 (owner1) -> heap ["Borrowing Value"]
println!("(Borrowing) {}", owner1); // not need reference. Why?
/*
STACK HEAP
────────────────────────────────── ──────────────────────
frame: main() ┌────────────────────┐
┌──────────────────────────────┐ │ "Borrowing Value" │
│ owner1 : String │ owns │ 15 bytes, UTF-8 │
│ ┌──────────────────────────┐ │ ─────────► │ [B][o][r][r][o]... │
│ │ ptr │ │ └────────────────────┘
│ │ len = 15 │ │
│ │ cap = 15 │ │
│ └──────────────────────────┘ │
│ │
│ reference1 : &String │
│ ┌──────────────────────────┐ │
│ │ ptr ──► owner1 (above) │ │ <── new slot in same frame
│ └──────────────────────────┘ │
└──────────────────────────────┘
frame: print_len( reference1 )
┌──────────────────────────────┐
│ s : &String (borrow) │
│ ┌──────────────────────────┐ │
│ │ ptr ──► reference1 │ │ (copy of the pointer, same address)
│ └──────────────────────────┘ │
└──────────────────────────────┘
└─► borrow ends when print_len() returns
reference1 still valid in main()
owner1 still valid in main()
*/
let reference1 = &owner1; // save in new stack's slot in main frame a ptr to owner1
// let reference2 = &owner1;
// let reference3 = &owner1;
print_len(reference1);
// print_len(reference2);
// print_len(reference3);
}