If you haven’t read this, it’s a good explanation of Box: http://doc.rust-lang.org/book/the-stack-and-the-heap.html.
As for Rc and Arc, I don’t know of a good guide for them, but I could try to explain them simply in terms of what they do.
Rc and Arc are (atomic) reference counted pointers, and act as an escape of the borrowing system. It puts the inner contents on the heap, like Box, but instead of using compile-time calculated lifetimes/scopes to determine when the data should be dropped, it keeps track of how many people have pointers to the data at runtime.
Arc/Rc are very useful for when you are storing data which you want to have access to from completely separate structs, and you really don’t know at compile time which struct will be dropped first. So, instead of finding out when to be dropped at compile time, whenever you use
.clone() on an Arc/Rc, it increments a “reference count” inside of itself and returns a new Arc/Rc pointing to the same data. When all cloned Arc/Rcs and the original Arc/Rc are dropped, the data is dropped, but if any are still being used it waits until they are all dropped.
Arc/Rc do have the restriction of not allowing any mutability however. Because they manually find out who is referencing the data at runtime, they don’t know at compile time if the reference you own is the only one with access to the data, so they don’t allow any mutability. To get mutability with Arc/Rc, you’ll want to use either Cell, RefCell (non-threadsafe), or Mutex or RWLock (threadsafe) depending on your needs and data type.
One last note: I’ve referred to/explained Rc and Arc at the same time, because they are basically exactly the same. The only difference is that Arc uses atomic variables to achieve thread safety, while Rc doesn’t. There’s a slight increase in overhead in using Arc, but Rc doesn’t support use between threads.