Da ein Teil meines Codes eine implizite Konvertierung zwischen Matrizen unterschiedlicher Typen erforderte (z. B. Matrix<int>
bis Matrix<double>
), habe ich einen Kopierkonstruktor für Templates Matrix<T>::Matrix(Matrix<U> const&)
anstelle des Standards Matrix<T>::Matrix(Matrix<T> const&)
definiert:
Mit einer geeigneten Typumwandlung, die dem Kopierkonstruktor hinzugefügt wurde, wurde diese Methode fehlerfrei zwischen Matrizen unterschiedlicher Typen konvertiert. Überraschenderweise schlägt es mit einem malloc-Fehler in der Situation fehl, in der ein einfacher Kopierkonstruktor funktionieren würde: where U == T
. Sicher, das Überladen des Kopierkonstruktors mit der Standard-Signatur Matrix<T>::Matrix(Matrix<T> const&)
behebt das Problem.
Dies ist eine schlechte Lösung, da es zu einer groß angelegten Duplizierung des Kopierkonstruktorcodes führt (wörtlich ein unverändertes Kopieren und Einfügen). Noch wichtiger ist, dass ich nicht verstehe, warum es einen doppelfreien malloc
Fehler ohne den doppelten Code gibt. Außerdem, warum ist hier die extrem ausführliche template <typename T> template <typename U>
-Syntax erforderlich, im Gegensatz zum Standard, und viel prägnanter, template <typename T, typename U>
?
Vollständige Quelle der Vorlagenmethode, kompiliert mit G ++ v4.0.1 unter Mac OS 10.5.
%Vor%Dies schlägt fehl, weil eine Vorlage die implizite Deklaration eines Kopierkonstruktors nicht unterdrückt. Es dient als einfacher konvertierender Konstruktor, mit dem ein Objekt kopiert werden kann, wenn die Überladungsauflösung es auswählt.
Nun haben Sie wahrscheinlich Ihre Matrix irgendwo kopiert, was den implizit definierten Kopierkonstruktor verwendet, der eine flache Kopie erstellt. Dann würden die kopierte Matrix und die Kopie in ihrem Destruktor den gleichen Zeiger löschen.
Außerdem, warum ist die extrem ausführliche
template <typename T> template <typename U>
Syntax erforderlich
Weil es zwei Vorlagen gibt: Die Matrix, eine Klassenvorlage, und die konvertierende Konstruktorvorlage. Jede Vorlage verdient eine eigene Template-Klausel mit eigenen Parametern.
Sie sollten übrigens <T>
in Ihrer ersten Zeile loswerden. So etwas erscheint beim Definieren einer Vorlage nicht.
Dies ist eine schlechte Lösung, da es zu einer doppelten Kopie des Kopierkonstruktorcodes
kommt
Sie können eine Memberfunktionsvorlage definieren, die die Arbeit übernimmt, und sowohl vom konvertierenden Konstruktor als auch vom Kopierkonstruktor delegieren. Auf diese Weise wird der Code nicht dupliziert.
Richard hat in den Kommentaren, in denen ich meine Antwort geändert habe, einen guten Punkt gemacht. Wenn die aus der Vorlage generierte Kandidatenfunktion besser übereinstimmt als der implizit deklarierte Kopierkonstruktor, dann gewinnt die Vorlage "und" wird aufgerufen. Hier sind zwei gängige Beispiele:
%Vor%Ein Kopierkonstruktor kann auch einen nichtkonstanten Referenzparameter haben, wenn eines seiner Mitglieder
hat %Vor%Ich bin nicht ganz klar von Ihrer Frage, aber ich vermute, was passiert, ist, dass der Standard-Kopierkonstruktor (der nur eine Memberwise-Kopie verwendet) an einigen Stellen in Ihrem Code verwendet wird. Denken Sie daran, dass nicht nur der Code, den Sie tatsächlich schreiben, den Kopierkonstruktor verwendet, sondern auch der Compiler.
Tags und Links c++ constructor type-conversion copy-constructor