Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.

Slides:



Advertisements
Ähnliche Präsentationen
Einführung in die Programmiersprache C/C++
Advertisements

Blue J.
Imperative Programmierung
Imperative Programmierung
Funktionen.
der Universität Oldenburg
der Universität Oldenburg
Christos, Kornelia, Jan Christos, Kornelia, Jan Entwicklungsumgebung Versteht unseren Java Programm Code Versteht unseren Java Programm.
Java: Objektorientierte Programmierung
Java: Dynamische Datentypen
Indirekte Adressierung
FH-Hof Indirekte Adressierung Richard Göbel. FH-Hof Einfache Speicherung von Daten Eine "einfache" Deklaration definiert direkt eine Speicherplatz für.
Java: Referenzen und Zeichenketten
Java: Grundlagen der Objektorientierung
SWITCH - Anweisung.
Datentyp- umwandlung. Literale sind: Bezeichner mit einem festen Wert wie z.B:
Klassenvariable (auch Klassendaten bzw. statische Attribute genannt) und statische Methoden.
Strukturen. In einer Struktur kann eine beliebige Anzahl von Komponenten (Daten) mit unterschiedlichen Datentypen (im Gegensatz zu Feldern) zusammengefaßt.
ARRAY oder FELD oder VEKTOR
Dynamischer Speicher. Ein Vergleich aus dem täglichen Leben...
Ein Beispiel in Java.
Dynamisches Array als "verkettete Liste". Ein Vergleich.
Erweiterte Zuweisungskompatibilität
Dynamischer Speicher und Struktur
Pointer. Grundsätzliches: Im Arbeitsspeicher werden Daten gespeichert. Um auf die Daten eindeutig zugreifen zu können, werden diesen Daten Adressen zugeordnet.
Klassenvariable. Da man für jede Kuh bzw. jede Henne auf dem Markt den gleichen Preis für ein Liter Milch, bzw. den gleichen Preis für ein Ei bekommt,
Konstruktoren.
Objekte werden als Adressen (Referenzen) übergeben. Dies führt manchmal zu unerwarteten Ergebnissen...
Parameterübergabe von zweidimensionalen Feldern in Funktionen.
Polymorphie (Vielgestaltigkeit)
Assoziationen (Beziehungen). Zwischen Objekten kann es eine Beziehung geben.
Polymorphie (Vielgestaltigkeit)
Objekte und Arbeitsspeicher
V AdresseWert public static void main(...){ int[] v; v=new int[2]; } Was veranlasst diese Anweisung im Arbeitsspeicher ? Es wird im Arbeitsspeicher.
ARRAY oder FELD oder VEKTOR
EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Vorlesung 2 SWS WS 99/00 Gisbert Dittrich FBI Unido
Programmieren mit JAVA
PKJ 2005/1 Stefan Dissmann Ausblick Es fehlen noch: Möglichkeiten zum Strukturieren größerer Programme Umgang mit variabler Zahl von Elementen Umgang mit.
PKJ 2005/1 Stefan Dissmann Rückblick auf 2005 Was zuletzt in 2005 vorgestellt wurde: Klassen mit Attributen, Methoden und Konstruktoren Referenzen auf.
Arrays,Strings&Pointer in C/C++
DVG Einführung in Java1 Einführung in JAVA.
Wichtige Fachausdrücke in C
Repetitorium PG : Pointer FH-Darmstadt, FB Informatik.
EPROG Tutorium Einheit 4 Klassen und Objekte. Wiederholung Schleifen do... while while for break/continue Strings String char Methoden für Strings Arrays.
Einführung in die Programmierung Wintersemester 2008/09 Prof. Dr. Günter Rudolph Lehrstuhl für Algorithm Engineering Fakultät für Informatik TU Dortmund.
Programmierung 1. Einführung Seite 1
Variablenkonzept Klassisch, in Java Basistyp
Programmieren in C Grundlagen C 2
Paul, Morten, Yannick Blue J. Entwicklungsumgebung  versteht Java Programmcode  Für die Entwicklung eigener Software  Durch die Programmierung.
Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen.
early binding (frühe Bindung) late binding (späte Bindung)
Informatik I : Software höhere Programmiersprachen Java Klassen: hat Methoden (Funktionen) und Daten (Variablen) es kann mehrere Klassen geben nur eine.
Einführung Blue J. Inhaltsverzeichnis  Definition  Vokabeln.
Paul, Morten, Yannick Blue J. Entwicklungsumgebung  versteht Java Programmcode  Für die Entwicklung eigener Software  Durch die Programmierung.
Erweiterte Zuweisungskompatibilität. Wie kann man Objekte verschiedener Klassen einer Klassenhierarchie einander zuweisen ?
Funktionen. Aufgabe : Eingabe zweier Zahlen ---> Minimum bestimmen Dann nochmals Eingabe zweier Zahlen ---> Minimum bestimmen.
Dynamisches Array als "verkettete Liste". Ein Vergleich.
Pointer. Grundsätzliches: Im Arbeitsspeicher werden Daten gespeichert. Um auf die Daten eindeutig zugreifen zu können, werden diesen Daten Adressen zugeordnet.
Funktionen, Felder und Parameter- übergabe. Funktionsaufruf mit Feld als Parameter: Parameter = Name des Feldes.
Tutorium Software-Engineering SS14 Florian Manghofer.
Tutorium Software-Engineering SS14 Florian Manghofer.
Tutorium Software-Engineering SS14 Florian Manghofer.
C++ FÜR cOMPUTERSPIELENTWICKLER
Tutorium Software-Engineering SS14 Florian Manghofer.
Tutorium Software-Engineering SS14 Florian Manghofer.
Strukturen (Eigenschaften) Strukturen dienen zur Zusammenfassung mehrerer Komponenten verschiedener Typen zu einer Einheit, die dann mit gemeinsamen Namen.
Pointer. * und &  Bei der Definition int var1; ○ // „normale“ Variable int *var2; ○ // Zeiger auf einen Integer int *var2 = NULL; ○ // … incl. Initialisierung.
Konstruktoren.
ARRAY oder FELD oder VEKTOR
Dynamisches Array als "verkettete Liste"
 Präsentation transkript:

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:

void f(){ int myfeld[10]; //... } int main(){ f(); //... } Erst wenn f aufgerufen wird, wird Speicher für myfeld auf dem Stack reserviert. Wieviel Byte sind dies ? 10 · Speicherbedarf (integer) 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(){ int anz, zahl, i; int *panf; cout << "Anzahl eingeben:"; cin >> anz; panf = new int[anz]; cout << "Zahlen eingeben:"; for(i=0; i<anz; i++){ cin >> zahl; *(panf+i)=zahl; } // panf[i]=zahl delete panf; } eingelesener Wert wird in anz gespeichert für ein Feld von anz integer-Werten panf zeigt auf das erste Element des Feldes Mögliche (gleichwertige) Formen des Zugriffs Reserviert dynamisch Speicher: gibt Speicher wieder frei

int main(){ int anz, zahl, i; int *panf; cout << "Anzahl eingeben:"; cin >> anz; panf = new int[anz]; cout << "Zahlen eingeben:"; for(i=0; i<anz; i++){ cin >> zahl; *(panf+i)=zahl; } // panf WelchenWert hat panf an dieser Stelle des Programmms ? Annahme: anz = 2 In der 1. Spalte stehen die Adressen der Variablen In der 2. Spalte stehen die Inhalte der Adressen (Werte der Variablen)

? panf int main(){ int anz, zahl, i; int *panf; cout << "Anzahl eingeben:"; cin >> anz; panf = new int[anz]; cout << "Zahlen eingeben:"; for(i=0; i<anz; i++){ cin >> zahl; *(panf+i)=zahl; } //... Was veranlasst diese Anweisungen ? Es wird im Arbeitsspeicher Platz für 2 integer-Zahlen reserviert und die (Anfangs)Adresse dieses Speicherbereichs der Variable panf zugewiesen. Auf die (Anfangs)Adresse dieses Speicherbereichs hat der Programmierer keinen Einfluß. Diese legt der Compiler bzw. Programmlader fest.

panf int main(){ int anz, zahl, i; int *panf; cout << "Anzahl eingeben:"; cin >> anz; panf = new int[anz]; cout << "Zahlen eingeben:"; for(i=0; i<anz; i++){ cin >> zahl; *(panf+i)=zahl; } // ? ? ? ? Speicherreservierung für 2 integer- Zahlen,die z.B. bei der Adresse 0700 beginnen ? zeigt auf: ? ? ? Annahme: Die 1. über Tastatur eingegebene Zahl sei 17 und die 2. eingegebene Zahl sei 13. Was bewirkt dann jeweils (insgesamt zweimal) diese Anweisung ?

panf int main(){ int anz, zahl, i; int *panf; cout << "Anzahl eingeben:"; cin >> anz; panf = new int[anz]; cout << "Zahlen eingeben:"; for(i=0; i<anz; i++){ cin >> zahl; *(panf+i)=zahl; } //

Man kann auch für Objekte dynamisch Speicher allokieren:

int main(){ Konto *pk; pk = new Konto; // Anweisungen delete pk; } new reserviert dynamisch Speicher. Die Anfangsadresse des dynamischen Speichers wird in einem Zeiger festgehalten, damit man später darauf 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(){ int anz; int *pi; Konto *pk, *pkk; anz = rand(); pi = new int; pk = new Konto; pkk = new Konto[anz];... Hier wird nachher jeweils der Anfang des dynamischen Speichers (in einem Zeiger) festgehalten. einen integer-Wert Zufallszahl die folgenden 3 Befehle reservieren Speicher für: für ein Objekt der Klasse Konto für ein Feld von anz Objekten der Klasse Konto

pk pkk int main(){ int anz; int *pi; Konto *pk, *pkk; anz = rand(); pi = new int; pk = new Konto; pkk = new Konto[anz];... pi Welchen Wert haben pi, pk, pkk an dieser Stelle des Programmms ? Annahmen: anz = 2 Speicherplatz Konto: 100 Byte In der 1. Spalte stehen die Adressen der Variablen In der 2. Spalte stehen die Inhalte der Adressen (Werte der Variablen)

? 120?pk ? pkk... pi int main(){ int anz; int *pi; Konto *pk, *pkk; anz = rand(); pi = new int; pk = new Konto; pkk = new Konto[anz]; Was veranlasst diese Anweisung ? Es wird im Arbeitsspeicher Platz für eine integer-Zahl reserviert und die (Anfangs)Adresse dieses Speicherbereichs der Variable pi zugewiesen. Auf die (Anfangs)Adresse des reservierten Speichers hat der Programmierer keinen Einfluß. Dies legt der Compiler (bzw. Programmlader fest).

?pk ? pkk... pi int main(){ int anz; int *pi; Konto *pk, *pkk; anz = rand(); pi = new int; pk = new Konto; pkk = new Konto[anz]; 0500? ? ? Speicherreservierung für ein integer, das z.B. bei der Adresse 0500 beginnt ? zeigt auf:

pk ? pkk... pi int main(){ int anz; int *pi; Konto *pk, *pkk; anz = rand(); pi = new int; pk = new Konto; pkk = new Konto[anz]; 0500? ? ? ? Speicherreservierung für ein Objekt der Klasse Konto (hier: 100 Byte) ? zeigt auf:... ? 0504

pk pkk... pi int main(){ int anz; int *pi; Konto *pk, *pkk; anz = rand(); pi = new int; pk = new Konto; pkk = new Konto[anz]; 0504? ? ?... Speicherreservierung für ein Feld der Länge 2 mit Objekten der Klasse Konto (hier: 2*100 Byte)... zeigt auf:... ? 0704 ?... ? 0604

pk pkk... pi *pi = 5; (*pk).setM('M'); // pk->setM('M'); (*(pkk+1)).setM('F'); // pkk[1].setM('F'); // (pkk+1)->setM('F'); delete pi; delete pk; delete [] pkk; } 0504? ? ?... ? 0704 ?... ? 0604

pk pkk... pi *pi = 5; (*pk).setM('M'); // pk->setM('M'); (*(pkk+1)).setM('F'); // pkk[1].setM('F'); // (pkk+1)->setM('F'); delete pi; delete pk; delete [] pkk; } gleiche Befehle, nur anders geschrieben Bemerkung: Die Zahl (hier 5) wird in den zur Verfügung stehenden 32 Bit gespeichert (in welchen Bits die einzelnen Ziffern der Zahl stehen, interessiert uns hier nicht).

pk pkk... pi *pi = 5; (*pk).setM('M'); // pk->setM('M'); (*(pkk+1)).setM('F'); // pkk[1].setM('F'); // (pkk+1)->setM('F'); delete pi; delete pk; delete [] pkk; } 0504M 0604 ? ?... ? 0704 ?... ? gleiche Befehle, nur anders geschrieben

pk pkk... pi *pi = 5; (*pk).setM('M'); // pk->setM('M'); (*(pkk+1)).setM('F'); // pkk[1].setM('F'); // (pkk+1)->setM('F'); delete pi; delete pk; delete [] pkk; } 0504M 0604 ? ?... ? 0704 F... ?

Was macht das gleiche Programm, aber ohne die folgenden Anweisungen: pi = new int; pk = new Konto; pkk = new Konto[anz];

int main(){ int anz; int *pi; 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 ' );... Welchen Wert hat pi z.B. an dieser Stelle des Programms ?

int main(){ int anz; int *pi; Konto *pk, *pkk; anz = rand(); *pi = 5; (*pk).setM('M'); (*(pkk+1)).setM('F'); ? pk pkk... pi ? bedeutet: irgendein unbekannter, zufälliger Wert. Zum Beispiel: 0815

int main(){ int anz; int *pi; Konto *pk, *pkk; anz = rand(); *pi = 5; (*pk).setM('M'); (*(pkk+1)).setM('F'); pk pkk... pi Was steht an der Adresse 0815 im Arbeitsspeicher ? Der Programmier weiß es nicht, denn er hat an dieser Adresse keinen Speicherplatz reservieren lassen und diesen entsprechend belegt. Im "schlimmsten" Fall könnte an der Adresse 0815 zum Beispiel... Ein Teil des Betriebssystems beginnen !

int main(){ int anz; int *pi; Konto *pk, *pkk; anz = rand(); *pi = 5; (*pk).setM('M'); (*(pkk+1)).setM('F'); pk pkk... pi 0815Teil des Syst. Betr.

int main(){ int anz; int *pi; Konto *pk, *pkk; anz = rand(); *pi = 5; (*pk).setM('M'); (*(pkk+1)).setM('F'); pk pkk... pi Dieser Teil des Betriebssystems wird überschrieben Analoges gilt auch für die folgenden Anweisungen