Frage

Ich habe ein Foo-Objekt und eine std :: Liste Instanzen davon halten. Mein Problem ist, dass, wenn ich eine neue Instanz der Liste hinzufügen, ist es zuerst den Ctor ruft dann aber auch den dtor. Und dann der dtor auf einem anderen Fall (nach der diesem Zeiger).

Eine einzige Instanz in die Liste aufgenommen wird, aber seit seinem dtor (zusammen mit ihren Eltern) aufgerufen wird, kann nicht das Objekt verwendet werden, wie erwartet.

Heres einige vereinfachte Code, um das Problem zu veranschaulichen:

#include <iostream>
#include <list>

class Foo
{
public:
    Foo()
    { 
        int breakpoint = 0;
    }
    ~Foo()
    { 
        int breakpoint = 0;
    }
};

int main()
{
    std::list<Foo> li;
    li.push_back(Foo());
}
War es hilfreich?

Lösung

Wenn Sie push_back () Ihre Foo Objekt, das Objekt kopiert , um die internen Datenstrukturen der Liste, damit der Dtor und die Ctor einer anderen Instanz aufgerufen werden.

Alle Standard-STL-Container-Typen in C ++ nehmen ihre Produkte nach Wert, kopieren sie daher je nach Bedarf. Zum Beispiel, wenn ein Vektor wachsen muss, ist es möglich, dass alle Werte in dem Vektor kopiert werden.

Vielleicht möchten Sie speichern Zeiger anstelle von Objekten in der Liste. Dadurch erhalten, dass nur die Zeiger anstelle des Objekts kopiert. Aber von so tun, müssen Sie sicherstellen, dass die Objekte zu löschen, sobald Sie fertig sind:

for (std::list<Foo*>::iterator it = list.begin(); it != list.end(); ++it) {
    delete *it;
}
list.clear();

Alternativ können Sie versuchen, eine Art von ‚Smart Pointer‘ Klasse zu verwenden, beispielsweise aus den Boost-Bibliotheken.

Andere Tipps

Sie erstellen eine temporäre Foo hier:

li.push_back( Foo() )

push_back Kopien, die Foo in seine internen Datenstrukturen. Die temporär Foo zerstört werden nach push_back ausgeführt wurde, die den destructor nennen.

Sie erhalten einen richtigen Copykonstruktor müssen, die auf den Teilnehmer, eine Referenzzahl erhöht, die Sie nicht wollen, früh zerstören - oder es privat machen Sie sich auf den Zeiger Lösung zu erzwingen

.

Verwenden Sie dieses Objekt zu verstehen:

class Foo
{
public:
    Foo(int x): m_x(x)
    { 
    std::cout << "Constructed Object: " << m_x << ")\n";
    }
    Foo(Foo const& c): m_x(c.m_x+100)
    {
    std::cout << "Copied Object: " << m_x << ")\n";
    }
    ~Foo()
    {  
    std::cout << "Destroyed Object: " << m_x << ")\n";
    }
};

Das erste Haupt

std::list<Foo*> li;
li.push_back(Foo(1));

Hier schaffen wir ein temporäres Foo Objekt und rufen push_back (). Das temporäre Objekt wird in die Liste und die Funktion zurückkehrt kopiert. Nach Abschluss dieser Anweisung wird das temporäre Objekt dann (über den destructor) zerstört. Wenn die Liste zerstört wird, wird es auch alle obejcts zerstören es enthält (Foo ist ein Objekt mit einem Destruktor so schließt Zerstörung der destructor Aufruf).

So Sie somthing so sehen sollte:

Constructed Object: 1
Constructed Object: 101
DestroyedObject: 1
DestroyedObject: 101

Im zweiten Beispiel haben Sie:

std::list<Foo*> li;
li.push_back(new Foo(1));

Hier können Sie dynamisch ein Objekt auf dem Heap erstellen. Dann rufen Sie die push_back (). Hier wird der Zeiger in die Liste kopiert (der Zeiger hat keinen Konstruktor / destructor), so dass nichts anderes passiert. Die Liste enthält einen Zeiger auf das Objekt auf dem Heap. Wenn die Funktion nichts anderes zurückkehrt erfolgt. Wenn die Liste zerstört wird es zerstört (man beachte die feinen Unterschied betweens zerstören und löschen), um das Objekt enthält (ein Zeiger), sondern ein Zeiger hat keine destructor so jede nichts passiert Sie ein Speicherleck wird.

So Sie somthing so sehen sollte:

Constructed Object: 1

tatsächlich Was hier passiert, ist, dass Sie speichern eine Kopie der übergebene Objekt in der Liste, weil Sie es von Wert zu senden sind, anstatt durch Bezugnahme eingeschlossen. So ist der erste dtor, die tatsächlich aufgerufen wird, auf dem Objekt aufgerufen werden Sie in der push_back-Methode übergeben, sondern eine neue Instanz hatte dann erstellt, und es wird nun in der Liste gespeichert.

Wenn Sie nicht wollen, eine Kopie des Foo Objekt Foo Objekte in der Liste, anstatt sich der Objekte erstellt, speichern Zeiger werden. Natürlich, wenn es zu tun haben Sie richtig auf Zerstörung der Listenspeicher freizugeben.

Erstellen die Liste Zeiger statt Instanzen löst das Problem mit dem destructor hält genannt zu werden. Aber ich möchte immer noch verstehen, warum es passiert.

#include <iostream>
#include <list>

class Foo
{
public:
    Foo()
    { 
        int breakpoint = 0;
    }
    ~Foo()
    { 
        int breakpoint = 0;
    }
};

int main()
{
    std::list<Foo*> li;
    li.push_back(new Foo());
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top