Rc<RefCell<T>>
- Rust course
- Intermediate
- Lesson 38/115
- 4 min
Combine Rc and RefCell for mutable data with multiple owners.
Rc<RefCell<T>>
Rc shares but doesn't allow changes; RefCell changes but doesn't share. Combined, they give data that several owners can change:
use std::cell::RefCell;
use std::rc::Rc;
let ortak = Rc::new(RefCell::new(Vec::new()));
let a = Rc::clone(&ortak);
let b = Rc::clone(&ortak);
a.borrow_mut().push("a");
b.borrow_mut().push("b");
println!("{:?}", ortak.borrow()); // ["a", "b"]It's common in structures like trees, graphs and observer lists.
The cycle danger
If two Rcs point at each other, their counters never reach zero and memory leaks. To prevent this, the link in the opposite direction is kept with Weak; Weak doesn't count as ownership:
let ebeveyn = Rc::new(RefCell::new(String::from("kök")));
let zayif = Rc::downgrade(&ebeveyn);
if let Some(e) = zayif.upgrade() {
println!("{}", e.borrow()); // kök
}upgrade() returns Some(Rc) if the value is still alive and None if it has been dropped.
Practice Shared list
Create a shared list with Rc::new(RefCell::new(Vec::new())) and take two copies (a, b). Add "a" through a and "b" through b. Print the list and the number of owners separated by a space.
Starter code
use std::cell::RefCell;
use std::rc::Rc;
fn main() {
// buraya yaz
}Sample solution
use std::cell::RefCell;
use std::rc::Rc;
fn main() {
let ortak = Rc::new(RefCell::new(Vec::new()));
let a = Rc::clone(&ortak);
let b = Rc::clone(&ortak);
a.borrow_mut().push("a");
b.borrow_mut().push("b");
println!("{:?} {}", ortak.borrow(), Rc::strong_count(&ortak));
}Expected output
["a", "b"] 3
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 Which combination does the same job across threads?
- Rc<RefCell<T>>
- Box<RefCell<T>>
- Arc<RefCell<T>>
- Arc<Mutex<T>> Correct answer
Explanation: RefCell isn't Sync; its thread-safe counterparts are Mutex and RwLock.
2 Shared and mutable
let ortak = Rc::new(____::new(Vec::new()));
let ortak = Rc::new(RefCell::new(Vec::new()));
Explanation: Rc provides sharing, RefCell provides mutation.
3 Type and capability
| Term | Meaning |
|---|---|
Rc<T> |
Sharing |
RefCell<T> |
Interior mutation |
Rc<RefCell<T>> |
Shared mutation |
Weak<T> |
Non-owning link |