Best Practice im Umgang mit per "new" erzeugten Objekten

trench140

Mitglied
Hallo allerseits,

ich frage mich aktuell, wie man am geschicktesten mit Objekten umgeht, welche z.B. zu einem weiteren Objekt gehören. Konkreten Beispiel, ich habe eine Klasse A welche eins oder mehrere Objekte der Klasse B beinhalten kann. Klasse A könnte z.B. so aussehen:

Code:
class A {
public:
    void append(B *b);
    B *getLast();
private:
    std::vector<B *> buffer;
}

Nun könnte append(B *b) wie folgt implementiert werden:

Code:
void A::append(B *b) {
    buffer.push_back(b);
}

// oder
void A::append(B *b) {
    // B besitzt einen Copy-Konstruktor
    buffer.push_back(new B(b));
}

Der erste Fall dürfte der schnellere sein, weil ich hier ja einfach nur einen Pointer speicher, dafür laufe ich Gefahr, dass falls b im aufrufenden Programmteil explizit mit delete gelöscht wird (warum auch immer) und somit die Daten aus dem Buffer korrupt sind.

Im zweiten Fall lege ich eine Kopie von b, womit die Konsistenz der Daten gesichert wird, allerdings habe ich natürlich einen erhöhten Zeitaufwand, da ja eine Deep-Copy des Objekts erzeugt werden muss. Zudem gibt es hier noch ein mögliches Memory Leak (?) wenn der Aufruf mittels
Code:
append(new B());
erfolgt, da ich den von "new B();" belegten Speicher, zumindest mit der obigen Methode, nicht mehr freigeben kann.

Gibt es für sowas eine Art "Best Practice" oder muss man das von Fall zu Fall entscheiden, je nachdem, was einem wichtiger ist (Laufzeit vs. Konsistenz vs. Speicherverbrauch)?
 
Hi

im Allgemeinen gilt:
Wo ein Objekt angelegt wird, soll es auch gelöscht werden.

Mach kein new in Collections, sondern lass das den äußeren Code machen.
Wenn der Programmierer vom äußeren Teil aus seine Objekte "versehentlich" löscht,
hat er in C++ sowieso nichts anderes als Probleme zu erwarten.

Wenn er nicht auf seine Objekte aufpassen kann, sollte er statt C++ lieber auf C# oder Java umsteigen.
Dort gibts mit dem Garbage Collector von Anfang an das umgekehrte Prinzip;
dH es gibt überhaupt kein delete mehr. Aufgeräumt wird mehr oder weniger automatisch, wenn ein Objekt nicht mehr gebraucht wird. Und die Erkennung davon ist gut genug programmiert, dass keine noch gebrauchten Objekte verschwinden.

Weiterer Grund: Ein Copykonstruktor ist manchmal unerwünscht, aus verschiedenen Gründen.
Dürfen die Objekte dann nicht Collections rein?
Ein "Copy"-konstrukor bekommt als Parameter übrigens ein Objekt (ggf. mit Referenz), aber keine Adresse.

Gruß
 
Hallo trench140,

bei komplexen Projekten ist es manchmal wirklich schwierig, immer den Überblick zu behalten an welcher Stelle Objekte noch verwendet werden. Da bieten sich sogenannte reference countable objects oder smart pointer an. Dem liegt das Prinzip zugrunde, das an jeder Stelle, an der in Objekt referenziert wird, ein Zähler inkrementiert wird und wenn das Objekt nicht mehr benötigt wird, wird der Zähler dekrementiert. Ist der Zähler gleich 0, wird das Objekt automatisch gelöscht oder erst am Programmende.

Hier kannst du dich zu dem Thema mal einlesen: http://ootips.org/yonat/4dev/smart-pointers.html

Allerdings bedeutet diese Technik natürlich einen höheren Programmieraufwand bzw. man muss sich die Unterstützung einer externen Bibliothek, z.B. boost, mit einkaufen.

Gruß
MCoder
 
Zurück