A reference gives access to a value without taking ownership of it. Think of it as a way to find the original value rather than a duplicate of that value. Create one with `&`; use `*` to dereference it when you need the value it refers to. For example, `let r = &a; let b = a + *r;` uses `a` through `r` without making a second `a`. section 2.6
References matter when code needs access but the caller still needs its value afterward. A function that takes an owned value can leave the caller unable to use it again. Borrowing asks for less: `&T` provides read-only access, while `&mut T` provides read-write access. section 4.5 section 4.5.1
Choose the access the operation needs:
- Use `for item in &collection` to read items and keep the collection available after the loop. section 2.4.1
- Use `for item in &mut collection` when the loop must change items. section 2.4.1
- Use an owned argument when the operation must take ownership. A function can borrow one argument while taking ownership of another. section 4.5.1
Send a message without giving away the satellite
A ground station can accept `to: &mut CubeSat` and `msg: Message`. Calling `send(&mut sat_a, msg)` lets the method change the satellite’s mailbox while the caller retains ownership of `sat_a` and can call `sat_a.recv()` afterward. The message itself moves into the mailbox. If `send` instead took `to: CubeSat`, ownership of the satellite would move into the function. section 4.5.1
Listing 4.13 Avoiding ownership issues with references
#[derive(Debug)]
struct CubeSat {
id: u64,
mailbox: Mailbox,
}
#[derive(Debug)]
struct Mailbox {
messages: Vec<Message>,
}
type Message = String;
struct GroundStation;
impl GroundStation {
fn send(&self, to: &mut CubeSat, msg: Message) {
to.mailbox.messages.push(msg);
}
}
impl CubeSat {
fn recv(&mut self) -> Option<Message> {
self.mailbox.messages.pop()
}
}
fn main() {
let base = GroundStation {};
let mut sat_a = CubeSat {
id: 0,
mailbox: Mailbox {
messages: vec![],
},
};
println!("t0: {:?}", sat_a);
base.send(&mut sat_a,
Message::from("hello there!")); #1
println!("t1: {:?}", sat_a);
let msg = sat_a.recv();
println!("t2: {:?}", sat_a);
println!("msg: {:?}", msg);
}
Follow the satellite before sending, after its mailbox receives the message, and after receiving it again. The call site and method signatures show which value is borrowed and which is moved. section 4.5.1
Underneath the syntax, a reference relates to an address in memory: it identifies where another value resides. Rust distinguishes references, which carry compiler safety guarantees, from raw pointers, which lack those standard guarantees and can be null. Raw pointers can be useful for examining memory, but reading through one is unsafe; prefer a reference when it provides the access you need. section 6.2 section 6.2.1
















