Zum Inhalt springen

auto_ptr


Orffi

Empfohlene Beiträge

Da ISO-C++ keinen Garbage Collector mitbringt, muß der Programmierer dafür sorgen, daß dynamisch reservierter Speicher wieder freigegeben wird. Man wird also zu jedem new ein delete im Quellcode finden. Leider sieht die Welt nicht immer ganz so einfach aus. Ein kleines Beispiel: Man hat eine Funktion, die Speicher dynamisch anfordert und am Ende wieder freigibt. Allerdings wird mitten in der Funktion, also zwischen new und delete, eine Exception ausgelöst.


void f (void)

{

   X *obj = new X();

   //mache irgendetwas...

   throw std::exception ();

   delete obj;

}

(Am Ende steht der komplette Quelltext, der auch kompilierbar ist.) Bei einem solchen Problem kommt der auto_ptr aus <memory> zum Einsatz. Denn, wie jeder leicht sieht, wird der Speicher nicht freigegeben und man hat ein Speicherloch, denn man hat keine Möglichkeit mehr auf den Speicher zuzugreifen, um ihn wieder freizugeben. Folgender Code hat so ein Speicherloch nicht:

void g ( void )

{

   std::auto_ptr<X> obj ( new X ( "auto" ) );

   throw std::exception ();

}

auto_ptr<> ruft den Destruktor des Objekt, welches er hält, automatisch auf, wenn die auto_ptr Variable den Sichtbarkeitsbereich verläßt. Die Funktion also normal verlassen wird oder durch eine Exception. Da ein auto_ptr nicht besonders schlau ist, kann er keine Referenzen zählen oder sonstwie herausfinden, wer nun auf das Objekt noch zeigt oder nicht. Deswegen passiert etwas sehr interessantes, wenn man einen auto_ptr in einen anderen kopiert. Nach: std::auto_ptr<X> obj2 = obj1; ist obj1 (was auch ein auto_ptr ist) NULL. Kopien von auto_ptr sind also alles andere als gleich!!! Niemals, wirklich niemals sollte man auf die folgende Idee kommen: std::vector<std::auto_ptr<X>> v; sort ( v.begin(), v.end() ); Hier wird intern natürlich hin- und herkopiert, um den Vector zu sortieren. Und bei jeder Kopieraktion ist das Original ein NULL-Pointer! Dies gilt übrigens nicht nur für vector sondern für alle Standard Container. Wie in Funktion i() (siehe unten) zu sehen ist, wird der auto_ptr wie ein ganz normaler Zeiger benutzt. Mit release() gibt der auto_ptr die Verwaltung für das Objekt auf. Man muß sich dann wieder selbst um die freigabe kümmern. Mit reset ('Objekt') kann man dem auto_ptr ein neues Objekt in die Obhut geben. Dabei wird das alte Objekt freigegeben. Hier nun ein komplettes Programm, das vielmehr erklärt als der ganze Text:

#include <iostream>

#include <memory>

#include <string>

#include <exception>


class X

{

      std::string name;

   public:

      X ( std::string );


      ~X ()

     {

        std::cout << "Destruktor Y: " << name << '\n';

     }


     std::string getName ()

     {

        return name;

     }

};


X::X ( std::string n) : name ( n )

{

   std::cout << "Konstruktor Y: " << name << '\n';

}


void f ( void )

{

   X *obj = new X ( "normal" );

   throw std::exception ();

   delete obj;

}



void g ( void )

{

   std::auto_ptr<X> obj ( new X ( "auto" ) );

   throw std::exception ();

}


void h ( void )

{

	std::auto_ptr<X> obj1 ( new X ( "obj1" ) );

	{

		std::auto_ptr<X> obj2 = obj1;

	}

	std:: cout << "^ Fuer obj1 wurde der Destruktor schon aufgerufen!?!\n";

	// weil das Original nach der Kopieraktion auf NULL zeigt.

}


void i ( void )

{

	std::auto_ptr<X> obj1 ( new X ( "Horst" ) );

	std:: cout << "Name des Objekts: " << obj1 -> getName () << '\n';

	obj1.reset ( new X ( "Karl" ) );

	X *obj2 = obj1.release();

}


int k ( void )

{

   std::auto_ptr<X> obj1 ( new X ( "Hugo" ) );

   X *obj2 = obj1.release();

   delete obj2;

}


int main ( void )

{

   try { f(); }

   catch ( std::exception &e )

   {

      std::cout << e.what () << '\n';

   }

   std::cout << "normal wird nicht freigegeben...\n";

   try { g(); }

   catch ( std::exception &e )

   {

      std::cout << e.what () << '\n';

   }


   h ();

   i ();

   std::cout << "Karl wird nicht freigegeben...\n";

   k ();


   return 0;

}

HTH

Jan

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...