Zum Inhalt springen
View in the app

A better way to browse. Learn more.

Fachinformatiker.de

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

auto_ptr

Empfohlene Antworten

Veröffentlicht

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

Archiv

Dieses Thema wurde archiviert und kann nicht mehr beantwortet werden.

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.