Any reference type &T
or &mut T
(including slice types like &str
or &[T]
) will only borrow data, and will not implicitly copy or move data when used.
You can explicitly copy from a reference to a type implementing Copy
by dereferencing it with *
, or from a reference to a type implementing Clone
by calling the clone
method. You can also explicitly move out of a mutable reference by replacing it with a different value, for example with std::mem::take
or std::mem::replace
.
Any data that's borrowed by at least one shared reference &T
must be read only for the lifetime of that reference, except for data inside a container with interior mutability, such as Cell<T>
, RefCell<T>
, Mutex<T>
and AtomicU32
.
Typically, the biggest limitation of using references is that their lifetime must be shorter than the lifetime of the owner of the data. In some cases, this may make code hard or impossible to express purely with references and lifetimes. Reference-counting pointers like Rc<T>
and Arc<T>
can help, as they generally act similar to shared references &T
, except that instead of borrowing data from some other location, the data is moved into the Rc
/Arc
and then the data ownership is shared between all clones of that Rc
/Arc
, elimitating the need for reference lifetimes, but at a small runtime cost.