2012-04-05 18 views
2

Ich schreibe eine generische Array-Klasse und Überladung von Operatoren für die Bequemlichkeit. Ich habe mein Array <> Objekt erhalten, um andere Array <> Objekte zu halten, aber ich habe Probleme beim Überschreiben des * -Operators. Ich brauche das linke Objekt zu kopieren, so dass mein Operator * Code ist dies:C++ Vorlage Kopieren Konstruktor Deep Copy

Array<T>& operator*(const double scalar) { 
    return Array<T>(*this) *= scalar; 
} 

(operator * = überlastet und Werk wurde).

overrode ich den Copykonstruktor wie folgt:

UPDATE: Neuer Copykonstruktor:

Array<T> (const Array<T>& copyfrom) { 
    size_=copyfrom.size(); 
    data=new T[size_]; 
    copy(&copyfrom.data[0], &copyfrom.data[size_], data); 
} 

Mein Gedanke ist, dass, wenn das Array nicht generisch war, aber immer mit einem primitiven gefüllt, würde dieser Code arbeitet . Aber ich denke, hier passiert etwas, weil ich eine Vorlage verwende, die Verhalten verursacht, das ich nicht erwarte. Das Datenarray im neuen "tief kopierten" Array verhält sich wie eine flache Zeigerkopie des Datenfeldes "copyrom".

Wie kann ich diesen Kopierkonstruktor für Primitive und Objekte mit Vorlagen arbeiten? Oder, noch besser, gibt es eine Möglichkeit, den Operator * zu überlasten, ohne sich Gedanken über Kopierkonstruktoren machen zu müssen? Vielen Dank.

EDIT: Hier ist der Code für operator*=. Ich denke immer noch, dass mein Problem in der Verwendung des Kopierkonstruktors liegt.

Array<T>& operator*=(const double scalar) { 
    for (int i=0; i<size_; i++) 
     data[i]*=scalar; 
    return *this; 
} 

EDIT: Ich erkannte, dass ich Probleme bekam, weil ich die size meiner inneren Arrays in meinem Array von Arrays ignoriert wurde. Die Dinge sind jetzt zuverlässiger. Jeder war wirklich hilfreich und ich denke, ich bin auf dem besten Weg, dies zum Laufen zu bringen. Mein operator= (was ich nicht überlastet hatte; guter Fang, Michael) ist jetzt wie unten. Es verhält sich wie erwartet, aber ich fange an, malloc Fehler in meinem Programm zu bekommen, und ich erkunde warum. Ist hier etwas mit der Speicherverwaltung nicht in Ordnung?

Array<T>& operator=(const Array<T>& a) { 
    if (this==&a) 
     return *this; 
    delete [] data; 

    size_=a.size(); 
    data=new T(size_); 
    copy(&a.data[0], &a.data[a.size()], data); 

    return *this; 
} 

EDIT: Ich reparierte die malloc Fehler! Meine Methoden funktionieren jetzt alle wie beabsichtigt. Die Speicherprobleme kamen, weil ich diese Methode header hatte:

template <typename T> 
static Array<T> matrixSolve (Array<Array<T> > m); 

Ich nahm ein Array von Arrays nach Wert. Alle möglichen Probleme. Nahm das Array als Referenz und alles hat geklappt. Danke für die Hilfe, alle!

+0

@MichaelAnderson Der Code für 'operator *' sollte 'this' nicht zurückgeben. Der Aufruf von 'Array (* this)' ruft den Kopierkonstruktor auf, den ich bestätigt habe. Außerdem bekomme ich keinen Kompilierfehler, wenn ich 'operator * =' verwende, wenn ich 'operator *' const mache, also darf ich 'this' nicht mutieren. – Enigmoid

+0

Sie haben Recht - ich werde diese Kommentare löschen. –

+0

Kannst du uns 'Array :: operator ='? Wenn Sie 'data [i] = copyrom.data [i]' verwenden, rufen Sie den 'operator =' für die Daten auf. Wenn das nicht definiert ist, erhalten Sie den Standard. Also, wenn Sie Arrays verschachteln und Array nicht = dann werden schlimme Dinge passieren. –

Antwort

3

Sie werden Ihre Betreiber * Member-Funktion wollen so etwas wie folgt aussehen:

Array<T> operator*(const double scalar) const { 
    Array<T> result(*this); 
    result *= scalar; 
    return result; 
} 

Wenn Sie eine Array<T> & zurückkehren, dann werden Sie einen Verweis auf eine temporäre zurückkehren, die zerstört werden, nicht definiertes Verhalten verursachen .

+0

Sie möchten wahrscheinlich auch 'operator *' const machen. –

+0

@MichaelAnderson: true - changed –

+0

Es ist nichts Schlechtes, diese drei Zeilen zu eins zusammenzufassen, wie im ursprünglichen Code des OP; in der Tat halte ich es für lesbarer, weil Sie nicht das Geräusch der Deklaration eines temporären Variablennamens einführen und es ist sofort sichtbar, dass Sie im Wesentlichen "' * this * = skalar "mit einem Backup machen". Es war nur die Rückgabe durch Verweis und das fehlende "const", das falsch war. – leftaroundabout