Ich habe eine mittlere komplexe C ++ - Klasse, die eine Reihe von Daten enthält, die von der Disc gelesen werden. Es enthält eine eklektische Mischung aus Schwimmern, Inten und Strukturen und wird nun allgemein verwendet. Während einer großen Code-Überprüfung wurde gefragt, ob wir einen benutzerdefinierten Zuweisungsoperator haben oder ob wir uns auf die vom Compiler generierte Version verlassen und wenn ja, woher wissen wir, dass sie richtig funktioniert? Nun, wir haben keine benutzerdefinierte Zuweisung geschrieben und daher wurde ein Komponententest hinzugefügt, um zu überprüfen, ob wir folgendes tun:
%Vor%dann ist datasetB dasselbe wie datasetA. Ein paar hundert Zeilen oder so. Jetzt ist der Kunde der Meinung, dass wir uns nicht darauf verlassen können, dass der Compiler (gcc) für zukünftige Versionen korrekt ist, und wir sollten unsere eigenen schreiben. Haben sie Recht, darauf zu bestehen?
Zusätzliche Informationen:
Ich bin beeindruckt von den bereits geposteten Antworten / Kommentaren und der Antwortzeit. Eine andere Art, diese Frage zu stellen, könnte sein: Wann wird eine POD-Struktur / -Klasse zu einer "Nicht-POD-Struktur / -Klasse"?
Es ist bekannt, was der automatisch erzeugte Zuweisungsoperator tun wird - das ist als Teil des Standards definiert, und ein standardkonformer C ++ - Compiler wird immer einen korrekt arbeitenden Zuweisungsoperator erzeugen (wenn nicht, dann wird er erzeugt) wäre kein standardkonformer Compiler).
Normalerweise müssen Sie nur Ihren eigenen Zuweisungsoperator schreiben, wenn Sie Ihren eigenen Destruktor oder Kopierkonstruktor geschrieben haben. Wenn Sie diese nicht benötigen, benötigen Sie auch keinen Zuweisungsoperator.
Der häufigste Grund, einen Zuweisungsoperator explizit zu definieren, ist die Unterstützung von "remote ownership" - im Prinzip eine Klasse, die einen oder mehrere Zeiger enthält und Eigentümer der Ressourcen ist, auf die sich diese Zeiger beziehen. In einem solchen Fall müssen Sie normalerweise Zuordnung, Kopieren (d. H. Kopierkonstruktor) und Zerstörung definieren. Es gibt drei primäre Strategien für solche Fälle (sortiert nach abnehmender Nutzungshäufigkeit):
Tiefe Kopie bedeutet das Zuweisen einer neuen Ressource für das Ziel der Zuweisung / Kopie. Z. B. weist eine String-Klasse einen Zeiger auf den Inhalt der Zeichenkette auf; Wenn Sie es zuweisen, weist die Zuweisung einen neuen Puffer für den neuen Inhalt im Ziel zu und kopiert die Daten von der Quelle in den Zielpuffer. Dies wird in den meisten aktuellen Implementierungen einer Reihe von Standardklassen wie std::string
und std::vector
verwendet.
Die Referenzzählung verwendet ist ebenfalls sehr verbreitet. Viele (meiste?) Ältere Implementierungen von std::string
verwendeten Referenzzählung. In diesem Fall haben Sie, anstatt die Daten für die Zeichenfolge zuzuordnen und zu kopieren, einfach eine Verweiszählung inkrementiert, um die Anzahl der Zeichenfolgenobjekte anzugeben, die sich auf einen bestimmten Datenpuffer beziehen. Sie haben nur dann einen neuen Puffer zugewiesen, wenn / wenn der Inhalt einer Zeichenfolge geändert wurde, so dass sie sich von anderen unterscheiden musste (d. H., Sie verwendete Kopie beim Schreiben). Beim Multithreading müssen Sie jedoch den Zugriff auf die Referenzzählung synchronisieren, was oft schwerwiegende Auswirkungen auf die Leistung hat. Im neueren Code ist dies ziemlich ungewöhnlich (meistens verwendet, wenn etwas so viele Daten speichert, wie es ist es lohnt sich, möglicherweise etwas CPU-Zeit zu verschwenden, um eine solche Kopie zu vermeiden).
Die Eigentumsübertragung ist relativ ungewöhnlich. Es ist, was von std::auto_ptr
getan wird. Wenn Sie etwas zuweisen oder kopieren, wird die Quelle der Zuweisung / Kopie grundsätzlich zerstört - die Daten werden von einem zum anderen übertragen. Dies ist (oder kann) nützlich sein, aber die Semantik unterscheidet sich ausreichend von der normalen Zuweisung, so dass sie oft nicht intuitiv ist. Gleichzeitig kann es unter den richtigen Umständen eine große Effizienz und Einfachheit bieten. C ++ 0x wird die Übertragung des Besitzes wesentlich kontrollierbarer machen, indem es einen unique_ptr
-Typ hinzufügt, der es expliziter macht, und auch rvalue-Verweise hinzufügt, die es einfach machen, Eigentumsübertragung für eine ziemlich große Klasse von Situationen zu implementieren, wo es möglich ist Verbesserung der Leistung ohne führt zu einer Semantik, die sichtbar kontraintuitiv ist.
Zurück zur ursprünglichen Frage, wenn Sie jedoch keine Remote-Eigentümerschaft haben - dh Ihre Klasse enthält keine Zeiger, ist es gut, dass Sie keinen Zuweisungsoperator explizit definieren ( oder dtor oder Kopie ctor). Ein Compiler-Fehler, der implizit definierte Zuweisungsoperatoren vom Arbeiten abhielt, würde verhindern, dass eine große Anzahl von Regressionstests bestanden würde.
Selbst wenn es irgendwie losgelassen würde, wäre deine Verteidigung dagegen, es einfach nicht zu benutzen. Es gibt keinen wirklichen Raum für die Frage, dass solch eine Veröffentlichung innerhalb weniger Stunden ersetzt werden würde. Bei einem mittelgroßen bis großen bestehenden Projekt möchten Sie nicht zu einem Compiler wechseln, solange es noch nicht lange verwendet wird.
Wenn der Compiler die Zuweisung nicht richtig generiert, dann müssen Sie sich größere Sorgen machen, als die Zuweisung der Zuweisung zu implementieren (wie die Tatsache, dass Sie einen fehlerhaften Compiler haben). Sofern Ihre Klasse keine Zeiger enthält, ist es nicht notwendig, eine eigene Überladung bereitzustellen. Es ist jedoch sinnvoll, eine explizite Überladung anzufordern, nicht weil der Compiler kaputt gehen könnte (was absurd ist), sondern vielmehr, um Ihre Absicht zu dokumentieren, dass die Zuweisung zulässig ist und sich auf diese Weise verhält. In C ++ 0x ist es möglich, Absicht zu dokumentieren und Zeit zu sparen, indem = default
für die vom Compiler generierte Version verwendet wird.
Tags und Links c++