Shallow copy -- i.e. copying data types with complex internal structures by only copying pointers at the upper level -- allows for very short run-time since most of the data is not copied physically but only referred to in the target object. The draw-back is that changing either of the objects involved in a shallow copy will alter the other object too. Especially in complex mathematical applications this often leads to errors hard to track down.
For that very reason we refrained from shallow copy semantics in assignments, that is after
one can change x or y without any impact on the other object, see also
Why Not Using Shallow Copy in Numerical Software.
Sub-matrices are a special case. The expression
Matrix E= sub_matrix(A, 2, 5, 1, 9);
means that E is defined as a mutable sub-matrix of A. Internally this is realized as a view on some of A's values. One could compare this to a window on A. As a result, modifications of E affect A and modifications of A change E if the change was in the range of rows and columns that E refers to. This admittedly behaves similarly to shallow copy behavior but is nevertheless different. In the case of a sub-matrix, we explicitly request aliasing. The modification of A can easily prevented by a const argument
const Matrix E= sub_matrix(A, 2, 5, 1, 9);
Furthermore, the sub-matrix of a const matrix (or another const sub-matrix) is const itself. Unless explicitly casted away, const-ness is conserved within MTL4 and cannot be circumvented like in other libraries with shallow copy assignment. Resuming, the construction of a matrix with sub_matrix is not a shallow copy but the definition of a reference to a part of another matrix.
Once sub-matrix is defined, assignments are regular deep copies, i.e.
copies the values of B to E and implicitly to the corresponding entries of A. Sub-matrices are not move semantics, i.e.
cannot use move semantics. It is correct regarding the destruction of the temporaries and the values of E but not concerning the modifications of A, which we defined E being a sub-matrix of.
If you do not want the aliasing behavior of sub_matrix but are only interested in the values of the sub-matrix, you can use the function clone.
Matrix F= clone(sub_matrix(A, 2, 5, 1, 9));
Then deep copy is explicitly used. F and A are thus entirely decoupled: any modification of either of them will not affect the other.
Any older remarks on inconsistencies between copy construction and assignment are invalid now. In addition, every expression that can be assigned can also be used in copy constructors, e.g.:
compressed2D<double> A(B * C * D + E);
Return to Why and How we use Functors Table of Content Proceed to Why Not Using Shallow Copy in Numerical Software