1

There is a similar, very popular question for C++, but I couldn't find a similar existing question for Rust.

So, what are the use cases for Box, Rc, Ref, RefMut (others?) in Rust?

The important part of the question (for me personally): when should smart pointers be used instead of references?

I know The Rust Book explains it very, very thoroughly, but I wish there would be a succinct and quick "cheatsheet" on the subject, possibly with some real-world examples that are missing in the book.

Nurbol Alpysbayev
  • 19,522
  • 3
  • 54
  • 89
  • 2
    The C++ question was asked in 2008. Stack Overflow was a different place back then, and the rules, expectations and community norms have changed over time. A lot of highly voted early questions would be considered too broad or off topic if asked today. That said, I think there is already a Rust question that is spiritually the same... – trent Nov 15 '19 at 23:00
  • 2
    ... namely, [Need holistic explanation about Rust's cell and reference counted types](https://stackoverflow.com/questions/45674479/need-holistic-explanation-about-rusts-cell-and-reference-counted-types). – trent Nov 15 '19 at 23:01
  • @trentcl Thank you so much for actually explaining why my question doesn't fit today's SO (I don't agree too much with this principle, but that's another subject), instead of silently downvoting. And thanks for the link! Looks like what I need. – Nurbol Alpysbayev Nov 15 '19 at 23:20

2 Answers2

6

What are the use cases for Box, Rc, Ref, RefMut (others?) in Rust?

Okay, here we go:

  • Box, in the simplest terms, is used when you have an object you want to keep on the heap. Use a box when
  • Rc is used when it is very difficult to decide on the lifetimes of objects. It's a sign of laziness to overuse, and somewhat defeats the purpose of lifetimes.
  • Ref and RefMut are the objects produced by a RefCell when you try to get access to its contents. A RefCell will track the borrowing state of its object at runtime instead of compile time, so it is kind of like lifetimes. A general use for this is when you need to have mutable references to many objects in a hashmap for example.
  • Arc is used with either RwLock (Essentially the same as RefCell apart from what's below) or Mutex when trying to share an object across a thread boundary. The examples on their pages will show you how to use them and why they are important as opposed to using the Rc<RefCell<T>> pattern.

There are a few more "smart" pointers per se in rust, but what you must know is that everything will eventually de-allocate its contents unless you've used unsafe code or used the global allocator directly.

This ties into why the tools built into the language (lifetimes) are so important to Rust, they accomplish all that Rc and RefCell accomplish but without the performance drawbacks and also do what C/C++ do without the chance of UB.

Optimistic Peach
  • 3,862
  • 2
  • 18
  • 29
  • 1
    Such a thorough, quality answer! And it's exactly what I was looking for. Thank you so much for your time and knowledge. I hope my question will be upvoted or un-downvoted eventually so that other people will be able to access this gem (your answer). – Nurbol Alpysbayev Nov 15 '19 at 23:35
1

The simple answer I would give would be: use references when you can. Unfortunately, understanding when you can depends on getting a deeper understanding of the borrow checker, and by that point, I would guess a cheat sheet would be less useful. However, some simple explanations might help.

  • The simple case is where you have a clear owner, and references are passed down the stack to functions that you call. This case works clearly for just references.
  • When you have the same clear ownership but the item is either "large", or of non-determined size, you may need a Box. Still a single owner, with possible stack-based borrowing.
  • When ownership isn't clearly in a tree, Rc or Arc would be appropriate (with something like a Mutex for sharing).

The other things mentioned (Ref, RefMut) are specifically about borrows of the thing contained in a RefCell. Cell and RefCell are containers that are mutable.

I would say, start by trying to just have your item owned, and using borrowed references to pass it around. If you do need sharing, look into Rc or Arc. If that still doesn't work, consider the other things.

Again, though, the Rust Book's description is very good, and you kind of have to get an understanding of borrowing to get a gut feeling of what to use anyway.

David Brown
  • 217
  • 4
  • 9
  • Thank you so much for your time! I was going to select your answer, when the other one popped out and I hope you'll agree it's more thorough and polished, also a bit more comprehensible for me personally. Still, I appreciate your answer very much, thank you. – Nurbol Alpysbayev Nov 16 '19 at 00:02