`Rc<T>`, the Reference Counted Smart Pointer - The Rust Programming Language

## `Rc<T>`, the Reference Counted Smart Pointer

In the majority of cases, ownership is very clear: you know exactly which variable owns a given value. However, this isn’t always the case; sometimes, you may actually need multiple owners. For this, Rust has a type called `Rc<T>`. Its name is an abbreviation for reference counting. Reference counting means keeping track of the number of references to a value in order to know if a value is still in use or not. If there are zero references to a value, we know we can clean up the value without any references becoming invalid.

To think about this in terms of a real-world scenario, it’s like a TV in a family room. When one person comes in the room to watch TV, they turn it on. Others can also come in the room and watch the TV. When the last person leaves the room, they’ll turn the TV off since it’s no longer being used. If someone turns off the TV while others are still watching it, though, the people watching the TV would get mad!

`Rc<T>` is for use when we want to allocate some data on the heap for multiple parts of our program to read, and we can’t determine at compile time which part of our program using this data will finish using it last. If we knew which part would finish last, we could make that part the owner of the data and the normal ownership rules enforced at compile time would kick in.

Note that `Rc<T>` is only for use in single-threaded scenarios; the next chapter on concurrency will cover how to do reference counting in multithreaded programs. If you try to use `Rc<T>` with multiple threads, you’ll get a compile-time error.

### Using `Rc<T>` to Share Data

Let’s return to our cons list example from Listing 15-5. In Listing 15-11, we’re going to try to use `List` as we defined it using `Box<T>`. First we’ll create one list instance that contains 5 and then 10. Next, we want to create two more lists: one that starts with 3 and continues on to our first list containing 5 and 10, then another list that starts with 4 and also continues on to our first list containing 5 and 10. In other words, we want two lists that both share ownership of the third list, which conceptually will be something like Figure 15-10:

Figure 15-10: Two lists, `b` and `c`, sharing ownership of a third list, `a`

Trying to implement this using our definition of `List` with `Box<T>` won’t work, as shown in Listing 15-11:

Filename: src/main.rs

    enum List {
        Cons(i32, Box<List>),
        Nil,
    }

    use 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));
    }

Listing 15-11: Having two lists using `Box<T>` that try to share ownership of a third list won’t work

If we compile this, we get this error:

    error[E0382]: use of moved value: `a`
      --> src/main.rs:13:30
       |
    12 |     let b = Cons(3, Box::new(a));
       |                              - value moved here
    13 |     let c = Cons(4, Box::new(a));
       |                              ^ value used here after move
       |
       = note: move occurs because `a` has type `List`, which does not
       implement the `Copy` trait

The `Cons` variants own the data they hold, so when we create the `b` list it moves `a` to be owned by `b`. Then when we try to use `a` again when creating `c`, we’re not allowed to since `a` has been moved.

We could change the definition of `Cons` to hold references instead, but then we’d have to specify lifetime parameters and we’d have to construct elements of a list such that every element lives at least as long as the list itself. Otherwise, the borrow checker won’t even let us compile the code.

Instead, we can change our definition of `List` to use `Rc<T>` instead of `Box<T>` as shown here in Listing 15-12:

Filename: src/main.rs

    enum List {
        Cons(i32, Rc<List>),
        Nil,
    }

    use 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, a.clone());
        let c = Cons(4, a.clone());
    }

Listing 15-12: A definition of `List` that uses `Rc<T>`

Note that we need to add a `use` statement for `Rc` because it’s not in the prelude. In `main`, we create the list holding 5 and 10 and store it in a new `Rc` in `a`. Then when we create `b` and `c`, we call the `clone` method on `a`.

### Cloning an `Rc<T>` Increases the Reference Count

We’ve seen the `clone` method previously, where we used it for making a complete copy of some data. With `Rc<T>`, though, it doesn’t make a full copy. `Rc<T>` holds a reference count, that is, a count of how many clones exist. Let’s change `main` as shown in Listing 15-13 to have an inner scope around where we create `c`, and to print out the results of the `Rc::strong_count` associated function at various points. `Rc::strong_count` returns the reference count of the `Rc` value we pass to it, and we’ll talk about why this function is named `strong_count` in the section later in this chapter about preventing reference cycles.

Filename: src/main.rs

    # enum List {
    #     Cons(i32, Rc<List>),
    #     Nil,
    # }
    #
    # use List::{Cons, Nil};
    # use std::rc::Rc;
    #
    fn main() {
        let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));
        println!("rc = {}", Rc::strong_count(&a));
        let b = Cons(3, a.clone());
        println!("rc after creating b = {}", Rc::strong_count(&a));
        {
            let c = Cons(4, a.clone());
            println!("rc after creating c = {}", Rc::strong_count(&a));
        }
        println!("rc after c goes out of scope = {}", Rc::strong_count(&a));
    }

Listing 15-13: Printing out the reference count

This will print out:

    rc = 1
    rc after creating b = 2
    rc after creating c = 3
    rc after c goes out of scope = 2

We’re able to see that `a` has an initial reference count of one. Then each time we call `clone`, the count goes up by one. When `c` goes out of scope, the count is decreased by one, which happens in the implementation of the `Drop` trait for `Rc<T>`. What we can’t see in this example is that when `b` and then `a` go out of scope at the end of `main`, the count of references to the list containing 5 and 10 is then 0, and the list is dropped. This strategy lets us have multiple owners, as the count will ensure that the value remains valid as long as any of the owners still exist.

In the beginning of this section, we said that `Rc<T>` only allows you to share data for multiple parts of your program to read through immutable references to the `T` value the `Rc<T>` contains. If `Rc<T>` let us have a mutable reference, we’d run into the problem that the borrowing rules disallow that we discussed in Chapter 4: two mutable borrows to the same place can cause data races and inconsistencies. But mutating data is very useful! In the next section, we’ll discuss the interior mutability pattern and the `RefCell<T>` type that we can use in conjunction with an `Rc<T>` to work with this restriction on immutability.