Rc Type
Suppose we have a dictionary of user settings in our program, and multiple components need to consult it throughout their lifetimes. No component can be considered the owner of the settings, so we lend out references:
fn load_preferences(components: &Vec<Component>) {
let settings = Settings::load();
for component in components {
component.configure(&settings);
}
}
But there's a problem here. If a component hangs on to the dictionary, its reference will outlive the owner. The compiler rejects this code because the lifetime of owner settings
ends when the function returns but the components continue on.
Rust's single ownership model is not a good fit for a shared value that has no clear owner. The fix is to turn off single ownership for the value. But if we turn it off, we need some other mechanism for identifying garbage and reclaiming memory. We fall back on reference-counted garbage collection with the Rc
abstraction, which wraps a value up with a reference counter.
We create an Rc
for a shared but not singly-owned value by calling the associated function Rc::new
. Its reference count is initially set to 1. The clone
method creates an additional reference that points at the shared value and increments the count by 1. When a reference goes out of scope, the counter is automatically decremented. When the counter reaches 0, the memory is freed.
This code creates a shared value of 91 and prints the reference count, which is exposed through the strong_count
method:
let outer;
{
let inner = Rc::new(91);
outer = inner.clone();
println!("{}", Rc::strong_count(&outer)); // prints 2
}
println!("{}", Rc::strong_count(&outer)); // prints 1
The shared value's reference count is 2 when both Rc
instances are in scope. It drops to 1 when inner
goes out of scope.
This code creates a new Rc
for the settings and passes clones to the components:
use std::rc::Rc;
fn load_preferences(components: &Vec<Component>) {
let settings = Rc::new(Settings::load());
for component in components {
component.configure(settings.clone());
}
}
The Rc
class is especially useful for doubly-linked lists and graphs. The nodes of these abstractions are pointed to by multiple other nodes, making singular ownership a poor fit.