Matrix-Klasse mit View-Funktionalität
Die Matrix-Klasse soll nun so erweitert werden, dass auch das View-Konzept realisiert wird. Ein Attribut isView soll festhalten, ob der Speicher verwaltet oder verwendet wird:
-
Soll der Speicher verwaltet werden, dann wird im Konstruktor Speicher allokiert und im Destruktor wieder freigegeben.
-
Soll der Speicher nicht verwaltet, sondern nur verwendet werden, dann wird im Konstruktor der Daten-Zeiger entsprechend gesetzt. Im Destruktor soll dann kein Speicher freigegeben werden.
Beim Copy-Konstruktor kann festgelegt werden, ob neuer Speicher angelegt werden soll oder Speicher einer anderen Matrix verwendet werden soll:
-
Bei einer echten Kopie wird Speicher angelegt und die Matrix kopiert:
Matrix A(4,5); init(A); Matrix B(A); B(0,0) = 42; print(A, "A"); print(B, "B");
-
Beim Übernehmen des Speichers erhält man eine Art Alias:
Matrix A(4,5); init(A); Matrix B(A, true); B(0,0) = 42; print(A, "A"); print(B, "B");
Realisiert dieses Konzept mit folgender Vorlage:
#include <cassert> #include <cstdio> struct Matrix { Matrix(long numRows, long numCols); Matrix(const Matrix &X, bool takeView=false); ~Matrix(); void operator=(const Matrix &X); const double & operator()(long i, long j) const; double & operator()(long i, long j); long numRows, numCols; double *data; bool isView; }; void init(Matrix &A, long offset=1) { for (long i=0; i<A.numRows; ++i) { for (long j=0; j<A.numCols; ++j) { A(i,j) = i+j*A.numRows+offset; } } } void print(const Matrix &A, const char *name = 0) { std::printf("\n[%s]\n", A.isView ? "view" : "no view"); if (name) { std::printf("%s =\n", name); } for (long i=0; i<A.numRows; ++i) { for (long j=0; j<A.numCols; ++j) { std::printf(" %5.1lf", A(i,j)); } std::printf("\n"); } std::printf("\n"); } int main() { Matrix A(4,5); init(A); Matrix B(A, true); B(0,0) = 42; print(A, "A"); print(B, "B"); }