C++ Operator für Subtraktion implementieren

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
alexander_ro
Beiträge: 298
Registriert: 16.01.2006 17:44:21
Lizenz eigener Beiträge: GNU General Public License

C++ Operator für Subtraktion implementieren

Beitrag von alexander_ro » 25.11.2020 10:33:41

Hallo ... :)

Ich wollte gerade eine Methode operator- bauen um geometrische Objekte zu subtrahieren. Dabei habe ich das Problem das der Destruktor für ein intern verwendetes Objekt zweimal aufgerufen wird.

Code: Alles auswählen

Material Material::operator- (Ausschnitt& objAusschnitt)
{
  Material objTmpMaterial (*this);

  long lOrdnerId = objTmpMaterial.treeIntBearbeitung.insOrdner ("Material");

  objTmpMaterial.mapIntBearbeitung[lOrdnerId] = "cube ( [" +
                                                 std::to_string (objTmpMaterial.geoIntGroesse (0, 0)) + ", " +
                                                 std::to_string (objTmpMaterial.geoIntGroesse (0, 1)) + ", " +
                                                 std::to_string (objTmpMaterial.geoIntGroesse (0, 2)) + "] );";

  return objTmpMaterial;
}
Ich benutze intern das Objekt treeIntBearbeitung und genau für dieses wird der Destruktor zweimal aufgerufen was beim freigeben des Speichers zu einem Absturz führt. Wenn man so eine Temporäre Kopie macht muss man sich dann um das Kopieren der intern verwendeten Objekt selbst kümmern?

Grüsse
Alexander

Benutzeravatar
schorsch_76
Beiträge: 2601
Registriert: 06.11.2007 16:00:42
Lizenz eigener Beiträge: MIT Lizenz

Re: C++ Operator für Subtraktion implementieren

Beitrag von schorsch_76 » 26.11.2020 06:53:26

Hallo Alexander,

es kommt darauf an ;)

Es gibt die sog. "rule of 3/5".
Die Dreierregel (vor C++11) bzw. Fünferregel (ab C++11) (englisch Rule of three bzw. Rule of five) bezeichnet in der Programmiersprache C++ eine Empfehlung, die besagt, dass in einer Klasse, die eine der folgenden drei bzw. fünf Elementfunktionen definiert, auch die jeweils anderen beiden bzw. vier definiert werden sollten.

Destruktor
Copy-Konstruktor
Copy-Zuweisungsoperator
Move-Konstruktor
Move-Zuweisungsoperator

Die Regel ist verpflichtender Bestandteil gängiger Konventionen wie z. B. C++ Core Guidelines oder AUTOSAR.
[3]
[KM01] concludes more precisely that “The Rule of Three is really two rules:
“If a class has a nonempty destructor, it almost always needs a copy constructor and an
assignment operator.

“If a class has a nontrivial copy constructor or assignment operator, it usually needs both of
these members and a destructor as well.”
Um es abzuschliessen:
Wenn ich eine dieser Funktionen brauche, schreibe ich alle 6. Constructor/Destruktor/Copy Constructor/Copy Assignment/Move Constructor/Move Assignment.
Wann brauche ich diese Funktionen? Wenn ich Resourcen habe um die ich mich kümmern muss.Speicher, Handles, Raw Pointer, File Handles ....

EDIT:
Nimm dir die Zeit und lese die C++ Core Guidelines durch :)

[1] https://en.cppreference.com/w/cpp/langu ... e_of_three
[2] https://de.wikipedia.org/wiki/Dreierregel_(C%2B%2B)
[3] www.open-std.org/jtc1/sc22/wg21/docs/pa ... /n3839.pdf
[4] https://github.com/isocpp/CppCoreGuidel ... md#Rc-five

alexander_ro
Beiträge: 298
Registriert: 16.01.2006 17:44:21
Lizenz eigener Beiträge: GNU General Public License

Re: C++ Operator für Subtraktion implementieren

Beitrag von alexander_ro » 26.11.2020 08:45:43

Danke für die vielen Infos und Links ... :)

Ob ich das Pauschal machen wollte bin ich mit nicht sicher weil Code der nicht gebraucht wird die Programme nicht unbedingt übersichtlicher macht. Das Tree Objekt ist schon viele Jahre alt und nie wurde eine solche Funktion gebraucht. Bis heute ...
Normal versuche ich Kopieren zu vermeiden. Für den operator- bin ich mir aber nicht sicher ob das geht ohne Probleme zu verursachen.

Das der nur den Pointer kopiert und nicht das Objekt hatte ich mir schon gedacht. Das wird nochmal auch in einem Deiner Links bestätigt. Wenn man sich im Destruktor die Speicheradresse des Tree-Objekts ausgeben lässt ist das ja schnell gefunden.

Eine Hübschere Lösung wäre wie in dem Wikipedia Link von Dir beschrieben die Verwendung von dem std::shared_ptr. Der kümmert sich selbst um die Problematik.

<Edit>
Passt jetzt zwar nicht ganz zum Thema ist mir aber wichtig weil es seit Jahrzehnten ein Riesen Problem in der Softwareentwicklung ist und diese Core Guidlines auch diesen Schwachsinn verbreiten. Das grösste Problem in der Softwareentwicklung ist nicht das Programmierer Fehler machen sondern das wenn ein Fehler passiert das Programm alle Informationen die man zum reparieren braucht das Programm mit ins Grab nimmt. Diese Guidlines Propagieren genau das als gutes Software Design und zeigen damit das sie nicht wirklich verstanden haben wo die Probleme liegen. Die behaupten man soll aus einem Destruktor keine Ausnahme werfen weil man den Fehler nicht mehr korrigieren kann daher ist gutes Design nur terminate zu verwenden. Das ist totaler Unsinn terminate beendet das Programm ohne jeden Kommentar. Das Aufrufende Programm hat nicht mehr die Gelegenheit den Umstand des Problems zu Dokumentieren. Das was die Guidlines fordern ist extrem schlechtes Design weil es verhindert das man das Problem leicht findet und beheben kann.

Auch der Verbreitete Irrglaube Ausnahme = Fehler ist Unsinn. Dem hat sogar der Erfinder von C++ schon mehrfach scheinbar aber Erfolglos widersprochen. Ausnahme ist es wenn etwas unerwartetes Passiert das muss aber noch lange kein Fehler sein.
</Edit>

alexander_ro
Beiträge: 298
Registriert: 16.01.2006 17:44:21
Lizenz eigener Beiträge: GNU General Public License

Re: C++ Operator für Subtraktion implementieren

Beitrag von alexander_ro » 01.12.2020 09:43:08

Ich habe das jetzt umgebaut auf einen shared_ptr. Damit funktioniert das bestens. Der kümmert sich um die Speicherverwaltung. Ich sehe jetzt nicht wirklich einen Grund warum ich da unbedingt 3 od. 5 Funktionen zusätzlich Pflegen soll.

Danke für Deine Hilfe ... hat mir sehr geholfen.

Antworten