Von einer verwandten (aber nicht gleichen) Frage - Warum definieren C ++ - Compiler nicht operator == und operator! =? :
Stroustrup sagte das über den Standard-Kopierkonstruktor in "Das Design und die Entwicklung von C ++" (Abschnitt 11.4.1 - Kopiersteuerung):
Ich persönlich finde es bedauerlich, dass Kopiervorgänge standardmäßig definiert sind und ich das Kopieren von Objekten vieler meiner Klassen verbiete. C ++ erbte jedoch seine Standardzuordnung und kopiert Konstruktoren von C, und sie werden häufig verwendet.
Die Antwort ist also, dass Stroutrup widerwillig die Rückwärtskompatibilität mit C aufgenommen hat (wahrscheinlich die Ursache der meisten Warzen von C ++, aber wahrscheinlich auch der Hauptgrund für C ++ 's Popularität).
Für meine eigenen Zwecke enthält der Ausschnitt, den ich für neue Klassen verwende, Deklarationen für einen privaten Zuweisungsoperator und einen Kopierkonstruktor, sodass ich beim Erstellen einer neuen Klasse keine Standardzuweisungs- und Kopieroperationen bekomme - das muss ich explizit tun entferne die Deklaration dieser Operationen aus dem privaten: Abschnitt, wenn ich möchte, dass der Compiler sie für mich generieren kann.
Von Die Programmiersprache C ++ , Abschnitt 11.3.4 Kopieren
... für Typen, bei denen der Standardkopiekonstruktor die richtige Semantik hat, bevorzuge ich diesen Standard. Es ist weniger ausführlich als alles, was ich schreiben kann, und die Leute sollten den Standard verstehen. Außerdem wissen Compiler über den Standard und seine möglichen Optimierungsmöglichkeiten. Darüber hinaus ist das Schreiben der Memberwise-Kopie von Hand langwierig und fehleranfällig für Klassen mit vielen Datenelementen.
Grundsätzlich lese ich, dass der Standard-Kopierkonstruktor Ihnen den Aufwand erspart, Sie vor langwierigen Fehlern bewahrt und Ihren Code optimiert, indem Sie die Versuchung beseitigen, ihn von Hand zu optimieren (indem Sie es dem Compiler überlassen). .
Weil sonst, wenn Sie eine Instanz nach Wert übergeben, wie könnte der Compiler einen erzeugen?
Ich weiß nicht, warum es ursprünglich so entworfen wurde. Aber als Benutzer kann ich sagen, warum ich froh bin, dass sie es getan haben.
Das Gleiche gilt für den Standardzuweisungsoperator. Die meisten Leute a) definieren ihren Copy-Konstruktor / equals-Operator falsch oder können ihn nicht verwalten. Ich habe viele Bugs in C ++ - Code entfernt, indem ich auf RAII-Typen umschalte und handcodierte Operatoren / Kopierkonstruktoren lösche.
Einige Punkte:
Es ist wichtig zu kontrollieren, ob ein Objekt kopiert werden kann oder nicht.
Wenn Sie nicht möchten, dass ein Objekt kopiert werden kann, können Sie den Kopierkonstruktor als privat deklarieren (und in C ++ 0x können Sie =delete
sagen). Dies ist bei Ihrem Vorschlag unverändert, jedoch ist das Problem einfach umgekehrt, d. Sie könnten eine Frage voraussehen wie: "Warum generiert der Compiler keinen standardmäßigen Kopierkonstruktor, wenn er weiß, was zu tun ist?"
Dies wird auch in C ++ 0x angesprochen, da ich glaube, dass es ein =default
-Flag gibt, mit dem Sie es angeben können:
Es ist vorteilhaft, dass der Compiler die bestmögliche Version des Kopierkonstruktors implementiert.
Abgesehen von der Benutzerfreundlichkeit ist der Compiler heute in der Lage, die effizienteste Technik zum Kopieren des Objekts zu wählen. Zum Beispiel könnte es einfach memcpy mit dem Objekt verwenden, wenn es weiß, dass dies sicher ist.Mit Ihrem Vorschlag müsste der Compiler, um eine ähnliche Optimierung heute zu erreichen, den Konstruktorkörper analysieren, um zu überprüfen, dass er nur alle Elemente flach kopiert. Dies ist nicht nur nicht trivial, sondern kann im Allgemeinen nur auftreten, wenn der Konstruktorkörper für alle Übersetzungseinheiten sichtbar ist.
In C ++ 0x =default
wird dies umgangen.
Ich wäre nicht überrascht, wenn Compiler und statische Analysetools für C ++ 0x Warnungen über "implizite Standardelemente im alten Stil" generieren würden.
Wenn ein struct
von C-Code verwendet wird, muss ein Standardkopiekonstruktor vorhanden sein, um die C-Struct-Kopiersemantik beizubehalten.
Ich bin nicht sicher, was die "offizielle Linie" ist (habe kein Buch von Strastroup in meiner Nähe) und ich bin sicher, dass jemand es ausgraben wird.
In den meisten Fällen sind flache Kopien und die Standardinitialisierung jedoch "gut genug" besser für den Compiler, um sie zu liefern, als die Entwickler explizit zu schreiben.
Wenn der Entwickler diese Trivialkopie-Konstruktoren geschrieben hat und sich die Felder später ändern, liegt es an diesem Benutzer, die Änderungen vorzunehmen, und es könnte schwerwiegende Fehler geben, wenn er vergisst (z. B. wie sind diese Felder konstruiert?).
Wenn Benutzer nur dann Kopierkonstruktoren schreiben können, wenn wirklich etwas ausgefallen ist (z. B. tiefes Kopieren), reduzieren Sie die Häufigkeit dieser Fehler.
Ich denke, Sie kommen aus der falschen Richtung - wenn der Compiler einen vollständigen und korrekten 'Standard' -Konstruktor für jede Klasse oder Struktur schreiben könnte, würde sich niemand beschweren, oder? Das Problem ist, dass der Compiler das nicht zuverlässig ausführen kann. In diesen Fällen müssen Sie Ihre eigenen schreiben und den Standard überschreiben.
Weil C ++ kein Müll ist, zwingt es Sie dazu, alle Besitzer von Zeigern zu verfolgen, was in der Praxis unmöglich ist, es sei denn, Sie vereinfachen das Problem, indem Sie überall kopieren, so dass Sie zumindest wissen, wem es gehört die Kopie, und macht übrigens Ihr Programm langsamer als ein Müll gesammelt. Automatisch generierte Kopierkonstruktoren sind ein Nagel im Sarg, der dort platziert wurde, um das klaffende Loch in der Hölle zu verstecken, das neu und löschbar ist.
Tags und Links c++ compiler-construction