Inhaltsverzeichnis:
- Eingeschränkter Gültigkeitsbereich in C ++
- Untersuchen des Bereichsproblems in C ++
- Bereitstellen einer Lösung unter Verwendung des Heaps in C ++
Video: Stackregister und die Arbeitsweise des Stacks 2024
Der Heapspeicher ist ein amorpher Speicherblock, auf den Ihr C ++ - Programm bei Bedarf zugreifen kann. Erfahren Sie, warum es existiert und wie Sie es verwenden können.
So wie es möglich ist, einen Zeiger an eine Funktion zu übergeben, ist es möglich, dass eine Funktion einen Zeiger zurückgibt. Eine Funktion, die die Adresse eines Double zurückgibt, wird wie folgt deklariert:
double * fn (void);
Sie müssen jedoch sehr vorsichtig sein, wenn Sie einen Zeiger zurückgeben. Um die Gefahren zu verstehen, müssen Sie etwas über den variablen Umfang wissen.
Eingeschränkter Gültigkeitsbereich in C ++
Gültigkeitsbereich ist der Bereich, über den eine Variable definiert ist. Betrachten Sie das folgende Code-Snippet:
// Die folgende Variable ist // für alle Funktionen zugänglich und so lange definiert, wie das // -Programm läuft (globaler Gültigkeitsbereich) int intGlobal; // Die folgende Variable intChild ist // nur für die Funktion zugänglich und wird nur // so lange definiert, wie C ++ child () oder eine // Funktion ausführt, die child () aufruft (function scope) void child (void) {int intChild;} // Die folgende Variable intParent hat eine Funktion // scope void parent (void) {int intParent = 0; Kind(); int intLater = 0; intParent = intLater;} int main (int nArgs, char * pArgs []) {parent ();}
Dieses Programmfragment beginnt mit der Deklaration einer Variablen intGlobal. Diese Variable existiert von dem Zeitpunkt an, an dem das Programm beginnt zu laufen, bis es endet. Sie sagen, dass intGlobal "Programmumfang hat. "Sie sagen auch, dass die Variable" in den Gültigkeitsbereich "geht, noch bevor die Funktion main () aufgerufen wird.
Die Funktion main () ruft sofort parent () auf. Das erste, was der Prozessor in parent () sieht, ist die Deklaration von intParent. Zu diesem Zeitpunkt geht intParent in den Gültigkeitsbereich - das heißt, intParent ist für den Rest der Funktion parent () definiert und verfügbar.
Die zweite Anweisung in parent () ist der Aufruf von child (). Wieder einmal deklariert die Funktion child () eine lokale Variable, diesmal intChild. Der Gültigkeitsbereich der Variablen intChild ist auf die Funktion child () beschränkt. Technisch gesehen ist intParent nicht im Bereich von child () definiert, da child () keinen Zugriff auf intParent hat; Die Variable intParent bleibt jedoch bestehen, während child () ausgeführt wird.
Wenn child () beendet wird, verliert die Variable intChild den Gültigkeitsbereich. Nicht nur ist intChild nicht mehr zugänglich, es existiert nicht mehr. (Der von intChild belegte Speicher wird an den allgemeinen Pool zurückgegeben, um für andere Dinge verwendet zu werden.)
Wenn parent () die Ausführung fortsetzt, geht die Variable intLater in den Gültigkeitsbereich der Deklaration. An dem Punkt, an dem parent () zu main () zurückkehrt, gehen sowohl intParent als auch intLater aus dem Gültigkeitsbereich heraus.
Da intGlobal in diesem Beispiel global deklariert ist, steht es allen drei Funktionen zur Verfügung und bleibt für die gesamte Lebensdauer des Programms verfügbar.
Untersuchen des Bereichsproblems in C ++
Das folgende Codesegment wird ohne Fehler kompiliert, funktioniert aber nicht (hasst du das nicht einfach?):
double * child (void) {double dLocalVariable; return & dLocalVariable;} void übergeordnetes Element (void) {double * pdLocal; pdLocal = Kind (); * pdLocal = 1. 0;}
Das Problem bei dieser Funktion besteht darin, dass dLocalVariable nur innerhalb des Gültigkeitsbereichs der Funktion child () definiert ist. Daher wird zu der Zeit, zu der die Speicheradresse von dLocalVariable von child () zurückgegeben wird, auf eine Variable verwiesen, die nicht mehr existiert. Der Speicher, den dLocalVariable früher belegt hat, wird wahrscheinlich für etwas anderes verwendet.
Dieser Fehler ist sehr häufig, da er sich auf verschiedene Arten ausbreiten kann. Leider führt dieser Fehler nicht dazu, dass das Programm sofort beendet wird. In der Tat kann das Programm die meiste Zeit gut funktionieren - das heißt, das Programm funktioniert weiter, solange der zuvor von dLocalVariable belegte Speicher nicht sofort wiederverwendet wird. Solche intermittierenden Probleme sind am schwierigsten zu lösen.
Bereitstellen einer Lösung unter Verwendung des Heaps in C ++
Das Problem des Bereichs kam dadurch zustande, dass C ++ den lokal definierten Speicher zurücknahm, bevor der Programmierer bereit war. Was benötigt wird, ist ein Speicherblock, der durch den Programmierer gesteuert wird. Sie kann den Speicher reservieren und zurücksetzen, wenn sie will - nicht weil C ++ denkt, dass es eine gute Idee ist. Ein solcher Speicherblock wird als Heap bezeichnet.
Der Heap-Speicher wird mit dem neuen Schlüsselwort zugewiesen, gefolgt vom Typ des zuzuweisenden Objekts. Der neue Befehl unterbricht einen Speicherblock aus dem Heap, der groß genug ist, um den angegebenen Objekttyp aufzunehmen, und gibt seine Adresse zurück. Zum Beispiel weist das Folgende eine Doppelvariable aus dem Heap zu:
double * child (void) {double * pdLocalVariable = new double; return pdLocalVariable;}
Diese Funktion funktioniert jetzt ordnungsgemäß. Obwohl die Variable pdLocalVariable den Gültigkeitsbereich verlässt, wenn die Funktion child () zurückgegeben wird, gilt dies nicht für den Speicher, auf den pdLocalVariable verweist. Ein von new zurückgegebener Speicherort verlässt den Gültigkeitsbereich nicht, bis er explizit mit dem Schlüsselwort delete, das speziell für diesen Zweck entwickelt wurde, an den Heap zurückgegeben wird:
void parent (void) {// child () gibt die Adresse zurück eines Blocks // des Heap-Speichers double * pdMyDouble = child (); // speichere einen Wert dort * pdMyDouble = 1. 1; // … // gibt jetzt den Speicher an den Heap zurück löschen pdMyDouble; pdMyDouble = 0; // …}
Hier wird der von child () zurückgegebene Zeiger verwendet, um einen doppelten Wert zu speichern. Nachdem die Funktion mit dem Speicherplatz beendet wurde, wird sie an den Heap zurückgegeben. Die Funktion parent () setzt den Zeiger auf 0, nachdem der Heapspeicher zurückgegeben wurde - dies ist keine Voraussetzung, aber es ist eine sehr gute Idee.
Wenn der Programmierer versehentlich nach dem Löschen versucht, etwas in * pdMyDouble zu speichern, stürzt das Programm sofort mit einer aussagekräftigen Fehlermeldung ab.
Sie können new auch zum Zuweisen von Arrays aus dem Heap verwenden, aber Sie müssen ein Array mit dem Schlüsselwort delete [] zurückgeben:
int * nArray = new int [10]; nArray [0] = 0; löschen [] nArray;
Technisch neu int [10] ruft den neuen Operator [] auf, funktioniert aber genauso wie neu.