Dynamische Speicherverwaltung

Beispielprogramm: NEWDEL.CPP

Das Programm NEWDEL.CPP ist ein erstes Beispiel für die Verwendung der Operatoren new und delete. Die Operatoren new und delete bewerkstelligen die dynamische Speicherbelegung und -freigabe in sehr ähnlicher Weise wie malloc() und free() in C.

Da die dynamische Speicherverwaltung in C sehr oft verwendet wird und dem ergo auch in C++ so sein würde, entschlossen sich die Entwickler von C++, dies als Teil der Sprache selbst zu implementieren, anstatt diese Funktionalität einer Bibliothek zu überlassen. Die Operatoren new und delete sind also ein Teil der Programmiersprache, genauso wie etwa der Additionsoperator. Deshalb sind diese Operatoren sehr effizient und einfach in der Anwendung wie wir in diesem Beispielprogramm sehen werden.

In den Zeilen 15 und 16 verwenden wir Zeiger wie wir es in C immerzu getan haben, Zeile 17 illustriert die Verwendung des new Operators. Dieser Operator verlangt ein Argument, das ein Typ sein muß, wie hier illustriert. Der Zeiger Zeiger2 zeigt nun auf die Variable vom Typ int, für die wir dynamisch Speicherplatz bereitgestellt haben. Die Ganzzahl kann genauso verwendet werden, wie jede dynamisch bereitgestellte Variable in ANSI-C verwendet wird. Die Zeilen 19 und 20 zeigen die Ausgabe des Wertes, der der Variable in Zeile 18 zugewiesen wurde.

In Zeile 21 führen wir eine weitere Variable dynamisch ein und Zeile 22 läßt Zeiger2 auf dieselbe dynamisch bereitgestellte Variable zeigen wie Zeiger1. In diesem Fall geht jede Referenz auf die Variable, auf die Zeiger2 zuerst zeigte, verloren und diese Variable kann nicht wieder verwendet oder freigegeben werden. Sie ist verloren im Speicher bis unser Programm die Kontrolle wieder an das Betriebssystem übergibt und der Speicherplatz neu belegt wird. Dies ist offensichtlich kein guter Programmierstil. Beachte, daß Zeiger1 in Zeile 26 mit dem Operator delete wieder freigegeben wird und Zeiger2 nun nicht mehr freigegeben werden kann, da er auf nichts zeigt. Da der Zeiger Zeiger1 selbst nicht verändert wird, zeigt er noch immer auf dieselbe Speicheradresse. Möglicherweise könnten wir diese Adresse noch einmal verwenden, aber das wäre schrecklicher Programmierstil, da wir keine Garantie haben, was das System mit dem Zeiger oder den Daten macht. Die Speicheradresse wird an die Liste der freien Adressen zurückgegeben und wohl bald wieder von einem Programm verwendet werden.

Da der delete Operator der Definition nach nichts tut, wenn ihm der Wert NULL übergeben wird, kannst Du das System zwar anweisen, die Daten, auf die ein Zeiger mit dem Wert NULL zeigt, zu löschen, allein es wird nichts passieren. Das ist also nur unnötiger Code. Der delete Operator kann nur solche Daten freigeben, die mit dem new Operator angefordert wurden. Wird der delete Operator mit irgendeiner anderen Art von Daten verwendet, ist die Operation nicht definiert und es kann eigentlich alles passieren. Nach dem ANSI Standard ist auch ein Systemabsturz ein erlaubtes Ergebnis dieser undefinierten Aktion und kann vom Autor des Compilers als solches definiert werden.

In Zeile 28 deklarieren wir einige Variablen vom Typ float. Du erinnerst Dich sicherlich, daß Du in C++ Variablen nicht am Anfang eines Blocks deklarieren mußt. Eine Deklaration ist eine ausführbare Anweisung und kann daher überall in einer Liste von solchen Anweisungen stehen. Eine der Variablen vom Typ float wird bei der Deklaration bereitgestellt, um zu zeigen, daß dies möglich ist. Wir wenden auf diese Variablen einige der Funktionen an, die wir zuerst auch auf die ganzzahligen Variablen verwendet haben.

In den Zeilen 36 bis 44 findest Du einige Beispiele für die Verwendung von Strukturen. Diese sollten eigentlich selbsterklärend sein.

Schließlich wirst Du Dich wundern, wie es möglich ist, einen Block von willkürlicher Größe festzulegen, wo doch der new Operator einen Typen als Argument verlangt, um die Größe des Blocks festzulegen. Um dies zu erreichen, verwenden wir das Konstrukt in Zeile 48. Hier belegen wir einen Speicher der Größe von 37 Variablen des Typs char, das heißt 37 Bytes. In Zeile 50 belegen wir einen Block, der um 133 Bytes größer ist als eine Datum Struktur. Dadurch wird klar, daß der new Operator mit all der Flexibilität von malloc() verwendet werden kann. Die eckigen Klammern in den Zeilen 49 und 51 sind notwendig, um dem Compiler zu sagen, daß er einen Array freigibt.

(weiter...)