Cell<T>
Goal of This Episode
Learn to modify values through shared references with Cell<T>, and understand its limitations.
Concept
Chapter 4 taught the borrowing rules: either one &mut or many &s, never both at once. Safe — but sometimes, holding only a & (shared reference), you still want to modify a value.
The Idea of Cell
Cell<T> provides interior mutability — even through a shared reference, it can copy values out with .get() and replace them with .set(v), no mutable reference required.
use std::cell::Cell;
fn main() {
let x = Cell::new(42);
x.set(100); // No mut needed!
println!("{}", x.get()); // 100
}
But .get() comes with one important restriction:
T Must Be Copy to Use .get()
Cell<T>’s .get() copies the value out (rather than borrowing). So T must implement Copy to use .get().
You can’t call .get() on a Cell<String>, since String isn’t Copy. Only Copy types work with .get() (i32, f64, bool, etc.).
Why Not Just Use mut?
Sometimes getting a &mut isn’t convenient. Say a struct is shared by reference in several places (&self), but you want to bump a counter inside it. Cell fits that scenario nicely.
Rc Is Built on Cell
The Rc<T> we learned about earlier needs a reference counter — +1 on every clone, -1 on every drop. But look at Clone’s signature: fn clone(&self) -> Self. It only gets &self (a shared reference), yet it must bump the count. How? With Cell! The counter inside Rc is a Cell<usize>, so the count can update even through &self.
Example Code
use std::cell::Cell;
struct Counter {
count: Cell<i32>,
name: String,
}
impl Counter {
fn new(name: String) -> Counter {
Counter {
count: Cell::new(0),
name,
}
}
// Note: only &self needed, not &mut self
fn increment(&self) {
let current = self.count.get();
self.count.set(current + 1);
}
fn get_count(&self) -> i32 {
self.count.get()
}
}
fn main() {
// Basic usage
let x = Cell::new(42);
println!("Original value: {}", x.get());
x.set(100);
println!("After modifying: {}", x.get());
// Using Cell inside a struct
let counter = Counter::new(String::from("visit count"));
// Only &counter (a shared reference), yet count can be modified
counter.increment();
counter.increment();
counter.increment();
println!("Count for {}: {}", counter.name, counter.get_count());
}
Recap
Cell<T>lets you modify a value without needing&mut..get()copies the value out;.set(v)writes a new one.Tmust beCopyto use.get()— becausegetcopies rather than borrows.- Great for “I only have
&selfbut want to modify a field” scenarios.