Cell<T>
- Rust course
- Intermediate
- Lesson 39/115
- 4 min
Learn interior mutability for Copy types with Cell<T>.
Cell<T>
Cell<T> is the lightest form of interior mutability. It gives no references; it takes the value as a whole (get, Copy types only) or puts one in its place (set, replace). Since there is no borrow counting, it never panics:
use std::cell::Cell;
struct Sayac {
n: Cell<u32>,
}
impl Sayac {
fn artir(&self) { // &self is enough!
self.n.set(self.n.get() + 1);
}
}Cell or RefCell?
For small Copy values (counters, flags), Cell is cheaper and safer. If you need a reference to the inner value (pushing to a vector, editing a String), RefCell is needed:
let bayrak = Cell::new(false);
bayrak.set(true);
let eski = bayrak.replace(false); // returns true
println!("{} {}", eski, bayrak.get()); // true falsePractice Counter with Cell
Write the Sayac type above with Cell<u32>. For let s = Sayac { n: Cell::new(0) }; (without mut), call artir three times and print the value.
Starter code
use std::cell::Cell;
fn main() {
// buraya yaz
}Sample solution
use std::cell::Cell;
struct Sayac {
n: Cell<u32>,
}
impl Sayac {
fn artir(&self) {
self.n.set(self.n.get() + 1);
}
}
fn main() {
let s = Sayac { n: Cell::new(0) };
s.artir();
s.artir();
s.artir();
println!("{}", s.n.get());
}Expected output
3
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 Can <code>get()</code> be called on a <code>Cell<String></code>?
- Yes, it returns a reference
- It panics
- No; get exists only for Copy types. Use take() or replace() Correct answer
- Yes, it returns a copy
Explanation: Since Cell can't give references, a non-Copy value can only be taken out by putting another value in its place.
2 Put the value
fn artir(&self) {
self.n.____(self.n.get() + 1);
}
fn artir(&self) {
self.n.set(self.n.get() + 1);
}
Explanation: Cell::set puts the new value in place.
3 Method and job
| Term | Meaning |
|---|---|
get() |
Gives a copy |
set(x) |
Puts it in place |
replace(x) |
Returns the old one |
take() |
Leaves the default |