2008-12-13 21 views

Antwort

18

Wenn Sie sich fragen, warum C++ - Klassen Destruktoren haben, haben einige Klassen andere Anforderungen als nur Speicher freizugeben. Möglicherweise haben Sie ein Objekt, dem eine Socket-Verbindung zugewiesen ist, die beispielsweise sauber heruntergefahren werden muss.

Auch "unscoping" ein Zeiger tut nicht geben Sie den Speicher frei, auf den es zeigt, da andere Zeiger darauf verweisen können.

Wenn Sie einen Zeiger auf den Stapel haben, wird beim Verlassen der Funktion der vom Zeiger verwendete Speicher freigegeben, aber nicht dieser Speicher, auf den der Zeiger zeigt. Es gibt eine subtile, aber sehr wichtige Unterscheidung.

14

Wenn ein Zeiger den Gültigkeitsbereich verlässt, wird der Speicher von der Zeiger freigegeben. Die 4 oder 8 Bytes (normalerweise) des Speichers, die vom Zeiger genommen werden, das heißt.

Die Objekt (oder einem anderen Speicher), dass der Zeiger nicht freigegeben ist, wenn der Zeiger den Gültigkeitsbereich verlässt. Sie tun das durch Löschen 'in den Zeiger. Und das ruft den Destruktor auf, falls es einen gibt.

0

Wenn ein Zeiger vorhanden ist (als Klassenmember vorhanden), sollte ein Destruktor für diese Klasse vorhanden sein, der das Objekt löschen soll, auf das der Zeiger verweist. Wenn Sie in der Klasse anstelle des Zeigers smart_pointer haben, brauchen Sie keinen Destruktor.

unter qn wird Ihnen helfen, besser zu verstehen. Will the below code cause memory leak in c++

9

Zuerst geben Sie fälschlicherweise an, dass der Speicher freigegeben wird, wenn der Zeiger den Bereich verlässt. Mit unformatierten Zeigern geht der Speicher verloren, und jede Ressource, die von dem spitzen Objekt gehalten wird.

Destruktoren sind ein Kernmerkmal der Sprache und die Basis für das RAII Idiom für Ressourcenmanagement. Objekte erwerben Ressourcen während der Konstruktion und geben dieselben Ressourcen im Destruktor frei. Es ist ein einfacher, kontrollierbarer und einfacher Ansatz für das Ressourcenmanagement. Beachten Sie, dass diese Ressource aus dem Speicher besteht (Smart Pointer Destruktoren geben den Speicher frei, den sie steuern, Container geben ihre interne Speicherstruktur frei) oder andere Ressourcen (Ofstreams geben offene Dateien frei, Datenbankverbindungen geben die Sockets frei). Wenn verwaltete Sprachen wie C# oder Java-Speicher automatisch vom Garbage Collector freigegeben werden, wird nur Speicher freigegeben, und der Benutzer hat die Last, alle anderen Ressourcen manuell am Verwendungsort zu steuern.

Wenn Sie Ausnahmesteuerungsstrukturen in C#/Java überprüfen, werden Sie feststellen, dass es in C++ keine finally-Klausel gibt. Der Grund dafür ist, dass verwaltete Sprachen dem Benutzer einen Code-Block bereitstellen müssen, der garantiert ausgeführt wird, um die Ressourcen manuell freizugeben. Die Belastung durch die Freigabe von Ressourcen wird in dem Programmierer platziert, der die Bibliotheken verwendet.

In C++, mit dem RAII-Idiom, jedes Objekt ist verantwortlich für die Ressourcen, die es hält und muss sie während der Zerstörung freigeben. Dies bedeutet, dass bei Verwendung von Objekten im Stapel Ressourcen ohne Benutzerinteraktion freigegeben werden. Die Verantwortung für die Ressourcensteuerung liegt in der Klasse, und der Benutzer muss nicht vergessen, jede Ressource manuell freizugeben.

Viele gemanagte Sprachbefürworter sagen gerne, dass es nicht von großem Vorteil ist, sich nicht merken zu müssen, wann oder wo man Speicher freigeben soll, wie es vom Müllsammler behauptet wird, aber sie werden nicht darüber diskutieren, wie andere Ressourcen kontrolliert werden . Speicherverwaltung ist nur eine Teilmenge des Problems der Ressourcenverwaltung und die gleiche Lösung gilt. Wenn Sie Speicher in intelligenten Zeigern halten (std :: auto_ptr, boost :: shared_ptr, std :: tr1 :: eindeutiges_ptr, std :: tr1 :: shared_ptr ..., wählen Sie das, das zu Ihrer Verwendung passt), dann wird der Speicher verwaltet für dich.

Während dieser Beitrag von der ursprünglichen Frage der Destruktoren abzustoßen scheint, ist es wirklich sehr eng verwandt. Alle Resource Controls müssen in Destruktoren ausgeführt werden, so funktionieren Smart Pointer: Wenn der Stack zugewiesene Smart Pointer den Gültigkeitsbereich verlässt, wird der Destruktor aufgerufen und überprüft, ob der Heap (neu) zugewiesene Speicher freigegeben ist und wenn ja, löschen heißt. Aber das ist nur eine Teilmenge des allgemeineren Problems.

0

Wenn Sie gutes C++ schreiben, dann sollten Sie sehr wenig Destruktoren haben (in der Tat denke ich, dass "einige Destruktoren" eine gute Metrik für die C++ - Codequalität sind).

Ein paar Ausnahmen ich denken kann, sind:

a) Wenn Sie mit den Dingen arbeiten, die sich nicht zerstören, zum Beispiel. "DATEI*".

b) Wenn Sie das "pimpl" Idiom verwenden (google für "pimpl idiom").

nb. Klassen wie std :: auto_ptr und std :: vector fallen in Kategorie (a), weil sie irgendwann einen C-artigen Zeiger auf den Speicher benötigen.

Verwandte Themen