Hallo Daniel,:Also: entweder mit Kopie oder mit Deiner
„schnellen Variante“ 
Beide Varianten lassen sich miteinander kombinieren, indem du eine Klasse als reinen Container implementierst, und eine andere Klasse die Darstellung einer Matrix übernimmt. Das hörst sich im ersten Moment ein wenig konfus an, macht aber durchaus Sinn. Bestes Beispiel ist die Implementierung der Klasse std::string, viele Compilerhersteller nehmen hier auch so eine Trennung vor (der C++ Standard weisst im übrigen explizit auf dieses Model hin) und beschleunigen die Implementierung mit COW Algorithmen.
Beispiel:
std::string t1(„hello world“);
legt ein übliche Zeichenkette an, nichts besonderes.
std::string t2( t1 );
Auf den ersten Blick wird die Zeichenkette t1 kopiert, bei genauerem hinsehen in die Quelltexte offenbart sich aber, hier wird nur zum schein kopiert. Der Trick besteht darin, dass ein std::string immer die gleiche größe hat, unabhängig davon, wieviele Zeichen im std::string stecken. std::string verweist stattdessen auf eine Instanz einer anderen Klasse, die die Speicherung von Zeichen übernimmt. Der Kopiervorgang sieht dann so aus, das t1 und t2 abschließend auf den gleichen Inhalt verweisen. Anders als ein strcpy werden also nicht ganze Speicherbereiche umkopiert, sondern nur Pointer.
Damit ergibt sich ein weiteres Problem, was passiert wenn t1 seinen Inhalt ändert, t2 darf dann nicht verändert werden. Die Lösung hierzu heisst COW = Copy On Write. In der Literatur und auch in google wirst du einiges zu diesem Thema finden. Im Prinzip geht es darum, das ein einzlenes Objekt geSHAREd wird, du sparst dir die Kosten für n gleiche Kopien. Im gleichen Zug werden Referenzen gezählt, der interne std::string weiss, wieviele std::string Objekte es referenzieren.
Muss ein interner std::string schreiben, also non-const, zugegriffen werden, so erzeugt das entsprechende std::string objekt eine Kopie und verwendet diese stattdessen.
Bezogen auf die Matrix sähe das in etwa wie folgt aus:
class Matrix{
MatrixImpl* pImpl;
};
class MatrixImpl {
int references; // wieviele Matrix-Objekte verweisen ?
};
Ein weiter Schritt besteht darin, die Matrix-Implementierung auf mehere spezialisierte Klassen aufzuteilen. Sicherlich benötigt ein Matrix Container eine sinnvolle standard-initialisierung, aber muss dafür jedesmal wertvoller Speicher allokiert werden?
class MatrixImpl; // eine rein abstracte Klasse
class UninitializedMatrix : public MatrixImpl …
Kannst du als Singleton realisieren, jede Methode wirft nur eine Exception. Spezielle, häufig verwendete Matrizen, werden ebenfalls mit einer eigenen Klasse bedacht.
Stell dir als analogie die Datentypen float, short und int vor, nimm an, sie werden durch eine Klasse implementiert. Du weisst, das Ergebnis durch die Addition von zwei short in jedem Fall in den Datentype int passt:
class Short {
Int operator+( const Short& ) const;
// ist der zweite Operand ein Float, sieht das schon anders aus
Float operator+(const Float& ) const;
};
Du schafft für deine speziellen Klassen angepasste Operatoren. Die Klassen Short, Int und Float sind eng miteinander verwand. Es handelt sich hier um einen Design Pattern, der in der Literatur auch als Family Pattern bekannt ist.
Ich hoffe so ein wenig neue Anregung gegeben zu haben.
Gruß Markus