CodeBlanks Logo Icon CodeBlanks

Rc<RefCell<T>>

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

main.rs
use std::cell::RefCell;
use std::rc::Rc;

fn main() {
    // buraya yaz
}

Sample solution

main.rs
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

Question
let ortak = Rc::new(____::new(Vec::new()));
Answer
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

All lessons in Intermediate