2009-08-21 30 views
5

Angenommen, ich habe eine generische Object-Klasse und eine generische List-Klasse. Ich möchte eine Liste dieser Objekte verwalten. Soll ich sie als List<Object> oder List<Object*> speichern?Speichern einer Liste von Objekten

Wenn ich List<Object> und ich habe eine Methode wie:

if(some_condition) { 
    Object obj; 
    myObjectList.append(obj); 
} 

Und meine Liste Klasse hält nur eine Referenz auf das Objekt, um so schnell wie die if-Anweisung beendet wird, wird das Objekt zerstört, und die Objekt, das ich gedrückt habe, wird ungültig. Also dann mache ich etwas wie:

Object *obj = new Object; 
myObjectList.append(*obj); 

So dass es nicht zerstört wird. Aber jetzt sind die Objekte nicht löschbar, oder? Weil sie jetzt sicher in der Liste als Objekte gespeichert sind, nicht als Zeiger auf Objekte, sodass ich sie nicht löschen kann ... oder werden sie automatisch zerstört, wenn sie aus der Liste entfernt werden?

In diesem Fall sollte ich wahrscheinlich List<Object*> verwenden und sie aus der Liste löschen, wenn ich mit ihnen fertig bin, nicht?

So verwirrt ... Ich bin sicher, dass ich irgendwo ein grundlegendes Missverständnis habe.

+0

Das Problem ist, dass Sie programmieren, wie dies ist Java ... es ist nicht. –

+2

Nun, ich komme nicht von einem Java-Hintergrund oder irgendetwas ... Ich bin heute Nacht ein bisschen zurückgeblieben. – mpen

Antwort

6

EDIT: Wie in einem Kommentar erwähnte boost::ptr_list ist noch besser, da es effizienter ist, und hat den gleichen Netto-Effekt als std::list<boost::shared_ptr<T> >.


EDIT: Sie erwähnen, dass Sie Qt in Ihrem Kommentar verwenden. Wenn Sie mit> = 4.5 können Sie Qt verwenden QList und QSharedPointer Klassen wie folgt aus:

QList<QSharedPointer<Object> > object_list; 
object_list.push_back(QSharedPointer<Object>(new Object)); 

Ich würde empfehlen, verwenden Sie std::list<>. Wahrscheinlich möchten Sie auch nur Zeiger auf die Objekte speichern, damit sie nicht ständig kopiert werden.

Unterm Strich also ist:

Angenommen, Sie haben eine Klasse namens Object. Sie sollten dies tun:

std::list<boost::shared_ptr<Object> > object_list; 
object_list.push_back(new Object); 

für C++ 14.11, für Auftrieb keine Notwendigkeit, verwenden Sie einfach die Standard-Smart-Pointer:

std::list<std::shared_ptr<Object>> object_list; 
object_list.push_back(std::make_shared<Object>()); 

Durch geteiltes Zeiger verwenden, erhalten die Objekte aufgeräumt automatisch, wenn sie aus der Liste entfernt werden (wenn kein anderer S darauf zeigt).

Sie könnten eine list<Object *> haben. Aber aufgrund Ihres Erfahrungslevels würde ich meinen, dass ein Referenzzeiger viel einfacher für Sie wäre.

In diesem Fall sollte ich wahrscheinlich Liste verwenden und sie von der Liste löschen, wenn ich mit ihnen fertig bin, nicht wahr?

Ja, das ist ein gangbarer Weg, aber ich empfehle intelligente Zeiger die „... und löschen Sie sie aus der Liste ...“ zu vermeiden, ganz Schritt.


HINWEIS:

auch das Beispiel Code, den Sie haben:

Object *obj = new Object; 
myObjectList.append(*obj); 

ist wahrscheinlich nicht das, was man wollte, das macht ein neues Objekt auf dem Heap, legt sie eine Kopie davon in der Liste. Wenn es danach keine delete obj gibt, dann haben Sie ein Speicherleck, da rohe Zeiger nicht automatisch delete d.

+0

Nun, ich würde lieber QList verwenden, da ich mit Qt arbeite. Aber ich denke, dass dein Vorschlag immer noch funktioniert. – mpen

+0

QList <> funktioniert fast identisch mit std :: list <>. Sie sind beide Templates und beide können Zeiger/Smart Pointer enthalten. –

+0

QList <> unterstützt auch STL-Stil-Iteratoren, so dass sie nett und kompatibel mit den generischen C++ - Algorithmen sind. –

3

Im ersten Fall wird das Objekt kopiert und nur das Original wird zerstört. Die andere Instanz wird in der Liste beibehalten.

In der zweiten Version können Sie den List-Destruktor verwenden, um die gespeicherten Objekte zu löschen.

+0

Oh ... Ich sehe, was passiert ist. Weil ich mit dem Code, an dem ich gerade arbeite, einen weiteren Zeiger in die Mischung geworfen habe ... Ich denke, einer war ungültig und einer nicht. Das erklärt einiges. – mpen

+2

Stellen Sie sicher, dass Sie einen 'tiefen' Kopierkonstruktor haben oder Sie möglicherweise einige wirklich unerwartete Ergebnisse erhalten. – DeusAduro

1

Verwenden Sie Zeiger, wie vorgeschlagen wurde. Sie verwenden "generische" Objekte, wahrscheinlich eine Basisklasse, und die Liste enthält tatsächlich einige abgeleitete Objekte, die an die Basis übergeben werden - das bedeutet, dass Sie den Zeiger an das ursprünglich erstellte Objekt übergeben müssen. Sonst wirst du den Polymorphismus aussortieren.

Die

class Base 
{ 
public: 
    int x; 
    virtual int getData() const { return x; } 
}; 
class Derived : public Base 
{ 
public: 
    int y; 
    virtual int getData() const { return y; } 
}; 

Derived obj1; 
obj1.x = 1; 
obj1.y = 2; 

Base obj2 = obj1; 
cout << obj2.getData(); 

Dieser wird 1 drucken, da obj2 nur eine Kopie des Basisteils von obj1 und ist wirklich eine Instanz von Base.

1

Sie könnten Liste verwenden, und dann, wenn es Zeit ist, ein Objekt an der Position x freizugeben, würden Sie so etwas wie

void erase_object(list* l, int i) { 
    delete (*list)[x] 
    list -> removeObj((*list)[x]); 
} 
2

als mit „alle“ Dinge verwenden, gibt es keine eine Antwort - die in Teufels die Details dessen, was Sie tun möchten oder was Ihre Einschränkungen sind.

Wenn die Objekte leicht sind und kein tiefes Kopieren erfordern, ist es effizienter, die kleinen Dinge als Kopien zu speichern. Andernfalls ist der Overhead von Smarts Pointers mehr als gerechtfertigt. Wenn Sie polymorPHic sind, können Sie Vorlagen verwenden.

Wenn es wichtiger ist, den Kopiervorgang zu minimieren und redundanten Code aus Vorlageninstanziierungen zu entfernen, verwenden Sie eine Liste von intelligenten, gemeinsam genutzten Zeigern.

Oder verwenden Sie eine Liste von nackten Zeigern, verwenden Sie new/delete, und achten Sie sorgfältig auf die Eigenschaften Ihres Zeigers.

Jede Liste verhält sich wie eine Liste, daher hängt die Auswahl der Listenimplementierung von Faktoren ab, die Sie hier nicht aufzählen.

Verwandte Themen