Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

11

05.07.2017, 18:11

Was wir übrigens bislang verschwiegen haben: Es gibt noch das Datensegment. Dort leben globale und statische Variablen. Das ist weder Heap noch Stack.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

12

05.07.2017, 18:11

Ich sagte auch nicht, dass es keine Register gibt oder dass keine involviert sind. Aber in Registern zu denken ist in Bezug auf C++ nicht immer sehr hilfreich.

Wenn wir schon Segmente aufzählen, gibt's auch noch das Code-Segment ;) Wobei das mit Segmenten in modernen CPUs mit virtueller Speicherverwaltung so 'ne Sache ist. Das ist nicht mehr so klassisch wie zu DOS-Zeiten, selbst die Segment-Register sind zu Selektoren umfunktioniert.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

13

05.07.2017, 18:25

An sich wird im C++-Standard auch gar nicht von 'Heap' und 'Stack' geredet, sondern nur von dynamische und automatische (und statische) Speicherallokationen. Am Ende machst du dir mit 'new' nen Objekt und erhältst durch nen Zeiger Zugriff auf dieses. Dabei wird zuerst ein freier Speicherblock gesucht und anschließend darin ein Objekt konstruiert. Mit 'Objekt' ist nicht notwendigerweise ein solches im Sinne einer Instanz einer mit 'class' (oder 'struct') definierten Klasse gemeint. Ein 'float' ist nach dem C++-Standard ein Objekt.

Der Vorteil ist nun, dass die Existenz eines solchen Objekts nicht an einen lokalen Geltungsbereich innerhalb einer Funktion gebunden ist, wie das bei automatisch Verwalteten Objekten auf dem Stack als lokale Variable der Fall ist. Du kannst es dann zerstören und den belegten Speicherbereich freigeben, wann du lustig bist. Beispielsweise Objekte in einem Spiel. Was es für Objekte sind und wieviele davon, ist vorher nicht bekannt. Somit müssen sie dynamisch angelegt werden.
Zudem ist der Stack ziemlich limitiert ist, was die maximale Größe angeht. Ein Array von mehreren Millionen ints (wofür man das auch immer brauchen sollte) ist demnach besser dynamisch angelegt.

Übrigens ist es ratsam, 'new' (und 'delete') nicht manuell zu verwenden. Neben dem versehentlichen Vergessen eines 'delete' sind auch andere Bugs möglich. Wenn du soweit bist, ließ dich mal in 'Smartpointer' ein.

TigerClaw25

unregistriert

14

05.07.2017, 19:30

Ok, besten Dank für die zahlreiche Infos.

Ich habe da einige Themen miteinander vermischt.

Eine Frage noch, wenn ich kein delete verwende, müsste ich außerhalb eines Blocks weiterhin auf die Adresse zugreifen können, funktioniert aber nicht:

C-/C++-Quelltext

1
2
3
4
5
6
    {
        int *pZeiger=NULL;
        pZeiger = new int;
        *pZeiger=100;
        }
        cout << *pZeiger << endl;

Ist die Adresse nicht weiterhin mit dem Wert 100 besetzt?

15

05.07.2017, 19:38

pZeiger lebt innerhalb des Blocks. Verwendest du ihn danach, wirft der Compiler nen Fehler, es sei denn, es gibt irgendwo eine weitere Variable 'pZeiger'. Übrigens solltest du dir nullptr statt NULL angewöhnen.

Tobiking

1x Rätselkönig

  • Private Nachricht senden

16

05.07.2017, 19:45


Eine Frage noch, wenn ich kein delete verwende, müsste ich außerhalb eines Blocks weiterhin auf die Adresse zugreifen können, funktioniert aber nicht:

C-/C++-Quelltext

1
2
3
4
5
6
    {
        int *pZeiger=NULL;
        pZeiger = new int;
        *pZeiger=100;
        }
        cout << *pZeiger << endl;

Ist die Adresse nicht weiterhin mit dem Wert 100 besetzt?

Die 100 steht immer noch in dem Speicher an der Adresse. Beim Verlassen des Scope wirfst du aber die Adresse / den Pointer weg und verlierst damit die Möglichkeit den Wert wiederzufinden. Das ist als wenn du dein Auto irgendwo parkst und dann vergisst wo es steht.

Du kannst mal ausprobieren dir im Scope die Adresse des Pointer ausgeben zu lassen und außerhalb des Scopes die Adresse wieder über eine Benutzereingabe einzugeben und daraus wieder einen Pointer zu erzeugen. Wenn du es richtig machst kannst du so wieder an die 100 kommen.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

17

05.07.2017, 21:11

Die 100 steht immer noch in dem Speicher an der Adresse. Beim Verlassen des Scope wirfst du aber die Adresse / den Pointer weg und verlierst damit die Möglichkeit den Wert wiederzufinden. Das ist als wenn du dein Auto irgendwo parkst und dann vergisst wo es steht.

Genau das ist der wichtige Punkt. Der Zeiger ist selbst wieder eine lokale Variable welche auf dein Array zeigt. Dein Array ist hinterher noch vorhanden, die Adresse ist jedoch weg.

Bisher dachte ich, dass die Zeiger an sich immer auf dem Heap sind, weil dadurch das Problem mit der Parameterübergabe von Funktionen bei großen Objekten umgangen wird, aber die Zuweisung einer Adresse an sich hat mit Heap/Stack nichts zutun, so viel hab ich bereits verstanden.

Ein Zeiger ist erst mal nur eine Variable. So wie ein int eine Ganzzahl oder ein char ein einzelnes Zeichen speichert, so speichert ein Zeiger eben eine Adresse. Stell dir das wie bei deinem Haus vor. Dein Haus hat eine Adresse, diese Adresse ist aber nicht dein Haus. Du kannst die Adresse auf ein Stück Papier schreiben und es mir schicken. Wenn ich das Stück Papier verbrenne so habe ich deine Adresse nicht mehr, dein Haus steht aber noch.
Jetzt ist es bei C++ ja so dass Objekte bei der Parameterübergabe kopiert werden.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
void useVariable(int i) {
  i = 1337;
}

void useFunction() {
  int a = 42;
  useVariable(a); // hier wird a kopiert und die Kopie an die Funktion übergeben
  // a hat hier immer noch den Wert 42
}

Bei einem Zeiger ist es das gleiche Spiel. Übergibst du einer Funktion einen Zeiger, so wird der Zeiger kopiert. Dabei werden nicht die Daten auf die der Zeiger zeigt kopiert, sondern nur die Variable die deren Adresse speichert. Das ist oft viel kleiner. Hast du ein Array mit 1000 Zahlen, so übergibst du einfach die Startadresse und zusätzlich die Größe deines Arrays. Kopiert werden jetzt ein Zeiger und eine Variable mit der Größe anstatt die 1000 Zahlen kopieren zu müssen. Bei anderen großen Objekten kannst du das eben genau so machen.
Was die Parameterübergabe angeht, wie schon angesprochen gibt es da noch die Referenzen. Die machen das Leben etwas einfacher.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

TigerClaw25

unregistriert

18

06.07.2017, 06:24

Guten Morgen,

"Übergibst du einer Funktion einen Zeiger, so wird der Zeiger kopiert. "
Wir mit foo(&var); nicht die Adresse an die Funktion übergeben?

"Der Zeiger ist selbst wieder eine lokale Variable welche auf dein Array zeigt. Dein Array ist hinterher noch vorhanden, die Adresse ist jedoch weg."
Erinnert mich ein wenig an statische Variablen, wobei da die Adresse weiterhin vorhanden bleibt.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

19

06.07.2017, 06:33

Klar wird da eine Adresse übergeben. Und zwar als Pointer-Variable über den Stack. Also wird die Adresse (in den Stack) geschrieben/kopiert.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

TigerClaw25

unregistriert

20

06.07.2017, 06:49

Stimmt. Das Buch "Der C++ Programmierer" hat einen merkwürdigen Schreibstil und die Themen sind teilweise nicht sinnvoll sortiert. Aber auf http://www.willemer.de/informatik/cpp/parameter.html habe ich was Entscheidendes dazu gefunden: "wird die Adresse der Variablen verwendet. Diese Adresse wird dann in eine Zeigervariable kopiert". Das Wort "kopiert" sagt genau das aus, was du auch erwähnt hattest. Danke.

Werbeanzeige