2024-05-06 20:40:05 +00:00
|
|
|
|
---
|
2024-10-29 18:27:12 +00:00
|
|
|
|
date: 2020-09-29
|
2024-05-06 20:40:05 +00:00
|
|
|
|
id: 13459bc1-66f2-4eed-b987-061bd0fbeb1c
|
|
|
|
|
title: Rc\<T\>
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
# Introduction
|
|
|
|
|
|
|
|
|
|
In the majority of cases, ownership is clear: you know exactly which
|
|
|
|
|
variable owns a given value. However, there are cases when a single
|
|
|
|
|
value might have multiple owners. For example, in graph data structures,
|
|
|
|
|
multiple edges might point to the same node, and that node is
|
|
|
|
|
conceptually owned by all of the edges that point to it. A node
|
|
|
|
|
shouldn’t be cleaned up unless it doesn’t have any edges pointing to it.
|
|
|
|
|
|
|
|
|
|
To enable multiple ownership, Rust has a type called `Rc<T>`, which is
|
|
|
|
|
an abbreviation for reference counting. The `Rc<T>` type keeps track of
|
|
|
|
|
the number of references to a value which determines whether or not a
|
|
|
|
|
value is still in use. If there are zero references to a value, the
|
|
|
|
|
value can be cleaned up without any references becoming invalid.
|
|
|
|
|
|
|
|
|
|
# Reason to choose Rc\<T\>
|
|
|
|
|
|
|
|
|
|
`Rc<T>` enables multiple owners of the same data;
|
|
|
|
|
[Box\<T\>](20200929135609-box_t) and
|
|
|
|
|
[RefCell\<T\>](20200929152628-refcell_t) have single owners.
|
|
|
|
|
|
|
|
|
|
# Example
|
|
|
|
|
|
|
|
|
|
This won't compile because b & c both share ownership of a:
|
|
|
|
|
|
|
|
|
|
``` rust
|
|
|
|
|
enum List {
|
|
|
|
|
Cons(i32, Box<List>),
|
|
|
|
|
Nil,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
use crate::List::{Cons, Nil};
|
|
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
|
let a = Cons(5, Box::new(Cons(10, Box::new(Nil))));
|
|
|
|
|
let _b = Cons(3, Box::new(a));
|
|
|
|
|
let _c = Cons(4, Box::new(a));
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The solution:
|
|
|
|
|
|
|
|
|
|
``` rust
|
|
|
|
|
enum List {
|
|
|
|
|
Cons(i32, Rc<List>),
|
|
|
|
|
Nil,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
use crate::List::{Cons, Nil};
|
|
|
|
|
use std::rc::Rc;
|
|
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
|
let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));
|
|
|
|
|
let _b = Cons(3, Rc::clone(&a));
|
|
|
|
|
let _c = Cons(4, Rc::clone(&a));
|
|
|
|
|
}
|
|
|
|
|
```
|