Hi, good questions.
To extract the storage of an ITensor, you don't actually need to involve MatrixRef or Ten. The storage is already in the form of a a std::vector, basically. I just added a code formula at the following link that will show you how to do it - please ask if you have any questions about it:
But to answer your other question about what Ten, TenRef, and TenRefc do, all of these classes Ten<R,V>, TenRef<R,V>, and TenRefc<R,V> are templated over a "range object" R and a value type V.
The range object defines the rule for mapping tensor indices to data (so like mapping the set 1,3,7 to the number 1+3d1+7d1*d2 where d1 and d2 are the dimensions of index 1 and 2). [At this point I should credit Ed Valeev's TiledArray library for motivating this design.] In addition to the basic tensor Range there is also the VecRange and MatRange which have fixed rank of either 1 or 2, which adds some extra efficiencies.
The value type V is either Real or Cplx (which is shorthand for std::complex).
Finally, Ten<R,V> is the basic tensor type which owns its data (basically it is a wrapper around a std::vector). TenRef is analogous to a pointer; it does not own its data but instead holds a pointer to some other data. This other data could be the std::vector inside a Ten object but could also be e.g. the storage of an ITensor. TenRefc is analogous to a const pointer. It is non-owning and provides read-only access to data.
Similar to pointers, if you have a TenRef "r" and another TenRef "o" then doing r=o just makes r point to the data pointed to by o. If you want to copy the underlying data, you must "dereference" the TenRef by doing r &= o. This operation copies the underlying data.
I'm planning to write about all of this in the ITensor book but it will be at least a few months before that happens.