8_dynamischer_Speicher_new

 Documents

 45 views
of 35
All materials on our website are shared by users. If you have any questions about copyright issues, please report us to resolve them. We are always happy to assist you.
Description
Dynamischer Speicher In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen wird…
Share
Transcript
Dynamischer Speicher In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen wird (nach dem Aufruf der Funktion), ist dieser Speicherbereich automatisch wieder freigegeben (nicht mehr reserviert). Beispiel: int main(){ Erst wenn f aufgerufen wird, wird Speicher für myfeld auf dem Stack f(); reserviert. //... Wieviel Byte sind dies ? } 10 · Speicherbedarf (integer) void f(){ int myfeld[10]; //... Nach dem Aufruf wird dieser Speicherplatz automatisch (ohne Zutun } des Programmmierers) wieder freigegeben. Beispiel: Man will die von einem Anwender (über Tastatur eingegebene) bestimmte Anzahl von Zahlen in einem Feld abspeichern. int main(){ int myfeld[1000]; //... } Welchen Nachteil hat dies bezüglich des Speicherplatzverbrauchs Der Anwender kann weniger Speicher – als reserviert – verbrauchen (z.B. bei Eingabe nur einer Zahl). Dies ist dann Speicherverschwendung. Um dies zu vermeiden kann der Anwender – während der Laufzeit des Programms – so viel Speicher reservieren, wie er benötigt. Im Gegensatz zum Beispiel oben wird diese Reservierung nicht beim Compilieren, sondern während der Programmlaufs gemacht und heißt deshalb dynamischer Speicher(reservierung). Realisierung in C++ int main(){ eingelesener Wert wird in int anz, zahl, i; anz gespeichert int *panf; Reserviert dynamisch Speicher: cout << "Anzahl eingeben:"; cin >> anz; für ein Feld von anz integer-Werten panf = new int[anz]; cout << "Zahlen eingeben:"; for(i=0; i> zahl; gibt Speicher wieder frei *(panf+i)=zahl; } Mögliche (gleichwertige) // panf[i]=zahl Formen des Zugriffs delete panf; panf zeigt auf das erste Element des Feldes } int main(){ Annahme: anz = 2 int anz, zahl, i; int *panf; cout << "Anzahl eingeben:"; WelchenWert hat cin >> anz; panf an dieser Stelle panf = new int[anz]; des Programmms ? cout << "Zahlen eingeben:"; for(i=0; i> zahl; *(panf+i)=zahl; } //... In der 1. Spalte stehen die Adressen panf 020 der Variablen ... ... In der 2. Spalte stehen die Inhalte der Adressen (Werte der Variablen) int main(){ Was veranlasst diese Anweisungen ? int anz, zahl, i; int *panf; cout << "Anzahl eingeben:"; cin >> anz; panf = new int[anz]; Auf die (Anfangs)Adresse cout << "Zahlen eingeben:"; dieses Speicherbereichs hat for(i=0; i> zahl; der Programmierer keinen *(panf+i)=zahl; Einfluß. Diese legt der } Compiler bzw. //... Programmlader fest. panf 020 ? Es wird im Arbeitsspeicher ... ... Platz für 2 integer-Zahlen reserviert und die (Anfangs)Adresse dieses Speicherbereichs der Variable panf zugewiesen. int main(){ Annahme: int anz, zahl, i; 0700 ? Die 1. über Tastatur eingegebene Zahl sei int 17cout *panf; und die<<2. eingegebene Zahl sei 13. "Anzahl eingeben:"; ? Was cinbewirkt dann jeweils (insgesamt >> anz; ? panf =diese zweimal) new int[anz]; Anweisung ? cout << "Zahlen eingeben:"; ? for(i=0; i> zahl; *(panf+i)=zahl; ? } //... zeigt auf: ? panf 020 0700 ? ... ... Speicherreservierung für 2 integer- Zahlen,die z.B. bei der Adresse 0700 beginnen int main(){ int anz, zahl, i; 0700 int *panf; cout << "Anzahl eingeben:"; cin >> anz; panf = new int[anz]; cout << "Zahlen eingeben:"; for(i=0; i> zahl; *(panf+i)=zahl; } //... panf 020 0700 ... ... Man kann auch für Objekte dynamisch Speicher allokieren: int main(){ new reserviert dynamisch Konto *pk; Speicher. Die Anfangsadresse pk = new Konto; des dynamischen Speichers wird in einem Zeiger festgehalten, // Anweisungen damit man später darauf delete pk; zugreifen kann. Zusätzlich wird } automatisch der Konstruktor aufgerufen. Falls kein Speicher mehr allokiert werden kann, bekommt pk den Wert NULL, den sogenannten Nullzeiger, zugewiesen. Dieser Nullzeiger zeigt auf kein Objekt ! delete gibt den dynamisch erzeugten Speicher wieder frei. Zusätzlich wird automatisch der Destruktor aufgerufen. Falls pk gleich NULL ist, wird keine Operation ausgeführt. In der schließenden Klammer } wird kein Destruktor aufgerufen, da pk eine Zeigervariable ist. Ein weiteres Beispiel: Die Klasse Bank hat u.a. das Attribut art (Datentyp char), in dem gespeichert ist, ob ein Konto einem Mitarbeiter gehört (‘M‘), oder einer fremden Person (‘F‘). Die zugehörigen Methoden, die diesen Modus setzen bzw. lesen heissen (aus Platzgründen verkürzt): setM getM class Bank { private: char art; ... public: void setM(...) ... In art wird die Art des }; Mitarbeiters gespeichert, also: 'M' oder 'F' Annahme: Ein Objekt der Klasse Bank sei 100 Byte groß. int main(){ Hier wird nachher jeweils der Anfang int anz; des dynamischen Speichers (in einem int *pi; Zeiger) festgehalten. Konto *pk, *pkk; Zufallszahl anz = rand(); pi = new int; die folgenden 3 Befehle reservieren Speicher für: pk = new Konto; pkk = new Konto[anz]; ... einen integer-Wert für ein Objekt der Klasse Konto für ein Feld von anz Objekten der Klasse Konto int main(){ Annahmen: int anz; anz = 2 Speicherplatz Konto: 100 Byte int *pi; Konto *pk, *pkk; Welchen Wert haben anz = rand(); pi, pk, pkk pi = new int; an dieser Stelle des Programmms ? pk = new Konto; pkk = new Konto[anz]; In der 1. Spalte stehen die Adressen pi 0100 der Variablen ... ... pk 0120 In der 2. Spalte stehen die Inhalte der ... ... Adressen (Werte der pkk 0140 Variablen) int main(){ Was veranlasst diese Anweisung ? int anz; int *pi; Auf die (Anfangs)Adresse Konto *pk, *pkk; des reservierten Speichers hat der Programmierer keinen anz = rand(); Einfluß. Dies legt der pi = new int; Compiler (bzw. pk = new Konto; Programmlader fest). pkk = new Konto[anz]; pi 100 ? Es wird im Arbeitsspeicher ... ... Platz für eine integer-Zahl pk 120 ? reserviert und die (Anfangs)Adresse dieses ... ... Speicherbereichs der Variable pkk 140 ? pi zugewiesen. int main(){ 0500 ? int anz; ? int *pi; Konto *pk, *pkk; ? anz = rand(); zeigt auf: ? pi = new int; pk = new Konto; pkk = new Konto[anz]; pi 0100 0500 ... ... pk 0120 ? Speicherreservierung für ein integer, das ... ... z.B. bei der Adresse pkk 0140 ? 0500 beginnt int main(){ 0500 ? int anz; ? int *pi; Konto *pk, *pkk; ? anz = rand(); ? pi = new int; 0504 ? pk = new Konto; ... pkk = new Konto[anz]; ... pi 0100 0500 zeigt auf: ? ... ... pk 0120 0504 Speicherreservierung für ein Objekt der ... ... Klasse Konto pkk 0140 ? (hier: 100 Byte) int main(){für Speicherreservierung 0504 ? int anz; ein Feld der Länge 2 mit ... int *pi; Objekten der Klasse Konto Konto *pk, (hier: 2*100 Byte) *pkk; ... anz = rand(); ? pi = new int; 0604 ? pk = new Konto; ... pkk = new Konto[anz]; ... pi 0100 0500 ? ... ... zeigt auf: 0704 ? pk 0120 0504 ... ... ... ... pkk 0140 0604 ? *pi = 5; 0504 ? (*pk).setM('M'); // pk->setM('M'); ... (*(pkk+1)).setM('F'); ... // pkk[1].setM('F'); ? // (pkk+1)->setM('F'); delete pi; 0604 ? delete pk; ... delete [] pkk; ... } pi 0100 0500 ? ... ... 0704 ? pk 0120 0504 ... ... ... ... pkk 0140 0604 ? *pi = 5; 0500 (*pk).setM('M'); // pk->setM('M'); (*(pkk+1)).setM('F'); // pkk[1].setM('F'); // (pkk+1)->setM('F'); delete Bemerkung: pi; delete pk; Die Zahl (hier 5) wird in den zur Verfügung stehenden delete [] (in 32 Bit gespeichert pkk;welchen Bits die einzelnen Ziffern }der Zahl stehen, interessiert uns hier nicht). pi 0100 0500 ... ... pk 0120 0504 ... ... gleiche Befehle, nur anders geschrieben pkk 0140 0604 *pi = 5; 0504 ‘M‘ (*pk).setM('M'); // pk->setM('M'); ... (*(pkk+1)).setM('F'); ... // pkk[1].setM('F'); ? // (pkk+1)->setM('F'); ? delete pi; 0604 delete pk; ... delete [] pkk; ... } pi 0100 0500 ? ... ... 0704 ? pk 0120 0504 ... ... ... ... gleiche Befehle, nur pkk 0140 0604 ? anders geschrieben *pi = 5; 0504 ‘M‘ (*pk).setM('M'); // pk->setM('M'); ... (*(pkk+1)).setM('F'); ... // pkk[1].setM('F'); ? // (pkk+1)->setM('F'); ? delete pi; 0604 delete pk; ... delete [] pkk; ... } pi 0100 0500 ? ... ... 0704 ‘F‘ pk 0120 0504 ... ... ... ... pkk 0140 0604 ? Was macht das gleiche Programm, aber ohne die folgenden Anweisungen: pi = new int; pk = new Konto; pkk = new Konto[anz]; int main(){ Welchen Wert hat pi z.B. int anz; an dieser Stelle des int *pi; Programms ? Konto *pk, *pkk; anz = rand(); *pi = 5; (*pk).setM('M'); // pk->setM('M'); (*(pkk+1)).setM('F'); // pkk[1].setM('F'); // (pkk+1)->setM('F'); ... int main(){ ? bedeutet: int anz; irgendein unbekannter, int *pi; zufälliger Wert. Zum Beispiel: 0815 Konto *pk, *pkk; anz = rand(); *pi = 5; (*pk).setM('M'); (*(pkk+1)).setM('F'); pi 0100 ? ... ... pk 0120 ... ... ... pkk 0140 ... int main(){ Was steht an der Adresse int anz; 0815 im Arbeitsspeicher ? int *pi; Der Programmier weiß es Konto *pk, *pkk; nicht, denn er hat an dieser anz = rand(); Adresse keinen *pi = 5; Speicherplatz reservieren (*pk).setM('M'); lassen und diesen (*(pkk+1)).setM('F');entsprechend belegt. pi 0100 0815 Im "schlimmsten" Fall ... ... könnte an der Adresse pk 0120 ... 0815 zum Beispiel... ... ... Ein Teil des pkk 0140 ... Betriebssystems beginnen ! int main(){ 0815 Teil int anz; des int *pi; Konto *pk, *pkk; Betr. anz = rand(); Syst. *pi = 5; (*pk).setM('M'); (*(pkk+1)).setM('F'); pi 0100 0815 ... ... pk 0120 ... ... ... pkk 0140 ... int main(){ 0815 5 int anz; 0 int *pi; Konto *pk, *pkk; 0 anz = rand(); 0 *pi = 5; (*pk).setM('M'); (*(pkk+1)).setM('F'); pi 0100 0815 Analoges gilt auch für die ... ... folgenden Anweisungen pk 0120 ... Dieser Teil des ... ... Betriebssystems wird pkk 0140 ... überschrieben
Related Search
We Need Your Support
Thank you for visiting our website and your interest in our free products and services. We are nonprofit website to share and download documents. To the running of this website, we need your help to support us.

Thanks to everyone for your continued support.

No, Thanks