new
.
Der damit allokierte Speicher kann mittels delete
wieder freigegeben werden.
(siehe Ex641.cc)
// Dynamic variable and // Dynamic array 1D #include <iostream.h> main() { int n,i; double *px, *pvar; cout << " Eingabe n : "; cin >> n; px = new double[n]; // Allocate array // initialize array for (i = 0; i < n; i++ ) { px[i] = (i+1)*(i+1); } // output x; for ( i = 0; i < n; i++) { cout << " " << px[i] << endl; } delete [] px; // Deallocate array pvar = new double; // Allocate variable *pvar = 3.5 * n; delete pvar; // Deallocate variable } |
Die Anweisung px = new double[n];
allokiert
n*sizeof(double)
Byte für den Zeiger px
.
Danach kann das dynamische Feld px
wie ein statisches Feld
behandelt werden. Allerdings nutzen dynamische Felder
den vorhandenen Speicherplatz besser, da dieser mit
dem delete
-Befehl freigegeben und anderweitig wieder genutzt werden
kann.
Achtung: Obige dynamische Feldvereinbarung ist nur für C++ gültig. In C müssen andere Befehle verwendet werden - hier die Unterschiede. (siehe Ex640.c)
C++ | C | ||
#include <malloc.h> |
|||
px = new double[n]; |
px = (double*) malloc(n*sizeof(double)); |
||
delete [] px; |
free(px); |
Ein zweidimensionales dynamisches Feld läßt sich einerseits durch ein eindimensionales dynamisches Feld darstellen (analog zu Variante 2 in § 5.1.2) als auch durch einen Zeiger auf ein Feld von Zeigern. Dies sieht für eine Matrix mit n Zeilen und m Spalten wie folgt aus. (siehe Ex642.cc)
// Dynamic array 2D #include <iostream.h> main() { int n,m,i,j; double **b; // pointer at pointers at double cout << " Eingabe Zeilen n : "; cin >> n; cout << " Eingabe Spalten m : "; cin >> m; b = new (double* [n]); // Allocate row pointers for (i = 0; i < n; i++) { b[i] = new double[m]; // Allocate rows } for (i = 0; i < n; i++ ) // initialize b { for (j = 0; j < m; j++) { b[i][j] = (i+1)*(j+1); } } ... for (i = n-1; i >= 0; i--) { delete [] b[i]; // Deallocate rows } delete [] b; // Deallocate row pointers } |
Zuerst muß der Zeiger auf die Zeilenpointer allokiert werden, erst danach kann der Speicher für die einzelnen Zeilen angefordert werden. Beim Deallokieren des Speichers müssen ebenfalls alle Zeilen wieder freigegeben werden. Für den Fall n = 3 und m = 4 veranschaulicht das Bild die Ablage der Daten im Speicher.
Achtung: Es gibt keine Garantie, daß die einzelnen
Zeilen der Matrix hintereinander im Speicher angeordnet sind.
Somit unterscheidet sich die Speicherung des dynamischen 2D-Feldes
von der Speicherung des statischen 2D-Feldes obwohl die Syntax
des Elementzugriffes b[i][j]
identisch ist.
Dafür ist diese Matrixspeicherung flexibler, da die Zeilen auch
unterschiedliche Längen haben dürfen (dünnbesetzte Matrizen oder
Matrizen mit Profil).
Zeiger können wiederum in Strukturen oder allgemeinen Typen auftreten. Hierbei ist allerdings größtmögliche Sorgfalt in der Verwendung der dynamischen Felder geboten, da für statische Variablen ansonsten unkritische Operationen plötzlich zu mirakulösem Programmverhalten führen können.
// Demonstration of w r o n g code // wrt. copying a structure with pointers #include <iostream.h> #include <strings.h> // strcpy, strlen struct Student2 { long long int matrikel; int skz; char *pname, *pvorname; // Pointers in structure }; main() { Student2 arni, robbi; char tmp[80]; // temp. input string cin >> tmp; // read vorname // Allocate memory for arni.pvorname arni.pvorname = new char[strlen(tmp)+1];// Don't forget "+1 strcpy(arni.pvorname,tmp); // and copy input on it // the same with the remaining data on arni ... // rough and w r o n g copying robbi = arni; // Point (A) ... delete [] arni.pvorname; // deallocate // Point (B) ... // Let us allocate some tiny dynamical array char *tiny; tiny = new char [5]; strcpy(tiny,"tiny"); // Point (C) ... } |
Wie sieht der Datenspeicher zu den Zeitpunkten (A), (B) und (C) aus?
robbi
besitzt keine eigenen dynamischen Felder.
delete [] arni.pvorname;
robbi.pvorname
adressierten
Speicherbereich frei und somit zeigt robbi.pvorname
auf einen nicht mehr reservierten Speicherbereich, welcher
vom Programm nach Gutdünken verwendet werden darf.
tiny = new char [5];
robbi.pvorname
auf die gleiche Adresse wie der Zeiger tiny
, sodaß
die Ausgabe der Daten von robbi.pvorname
mittels
cout << robbi.pvorname << endl;
robbi
eigene dynamische Felder allokiert werden
und die Inhalte der dynamischen Felder von arni
müssen auf diese kopiert werden.
(siehe Zuweisungsoperatoren und Copykonstruktoren für Klassen,
auch § 11).
(siehe Ex643-correct.cc)