C++

Objektlebensdauer und Speicherdauer in C++

Objektlebensdauer und Speicherdauer in C++
Beim Erstellen eines Objekts muss dessen Speicherort festgelegt werden, bevor es initialisiert wird. Initialisierung bedeutet Wert auf den Standort zu legen. Die Lebensdauer eines Objekts beginnt direkt nach der Initialisierung. Wenn ein Objekt stirbt, wird sein Standort (Speicher), den das Objekt eingenommen hat, freigegeben und dann der Computer heruntergefahren oder der Speicher von einem anderen Objekt belegt (verwendet). Das Freigeben eines Speichers bedeutet, dass die Kennung oder der Zeiger, der den Speicher belegt hat, ungültig wird. Die Lebensdauer eines Objekts endet, wenn sein Speicher freigegeben wird.

Es wird einige Zeit benötigt, um ein Objekt zu erstellen. Es wird einige Zeit benötigt, um ein Objekt zu töten. Wenn man über ein Objekt spricht, spielen zwei Dinge eine Rolle: der Ort, der die Lagerung darstellt, und der Wert. Die Bedeutung von Lebensdauer und Speicherdauer ist ähnlich; aber die Dauer wird eher vom Standort als vom Wert her gesehen. Die Speicherdauer ist die Zeit von der Zuordnung eines Ortes zu einem Objekt bis zur Trennung des Ortes vom Objekt.

Der Rest dieses Artikels veranschaulicht die Objektlebensdauer und erklärt kurz die unterschiedlichen Speicherdauern. Sie sollten Grundkenntnisse in C++ haben, um diesen Artikel zu verstehen. Sie sollten auch Kenntnisse im C++-Umfang haben.

Artikelinhalt

Illustration der Objektlebensdauer

Betrachten Sie das folgende Programm:

#einschließen
Verwenden von Namespace-Std;
int main()

wenn (1 == 1)

intx;
x = 1;
char y;
y = 'A';
cout << x << y << '\n';

0 zurückgeben;

Die Ausgabe ist, 1A .

Die Lebensdauer eines Objekts endet, wenn es ausserhalb des Geltungsbereichs geht. Die Lebensdauer von Objekt x beginnt bei „x = 1;“ und endet am Ende des if-local-scope. Die Lebensdauer von Objekt y beginnt bei „y = 'A';“ und endet am Ende des if-local-scope. Bevor beide Objekte sterben, werden sie in der cout-Anweisung verwendet .

Speicherdauer

Die Speicherdauer wird durch eines der folgenden Schemata bestimmt: automatische Speicherdauer; dynamische Speicherdauer; statische Speicherdauer; Fadenspeicherdauer. Speicherdauerkategorien, gelten auch für Referenzen.

Automatische Speicherdauer

Wenn eine Variable nicht explizit als static, thread_local oder extern deklariert ist, hat diese Variable eine automatische Speicherdauer. Beispiele sind x und y oben. Die Dauer solcher Variablen endet, wenn sie den Geltungsbereich verlassen. Das folgende Programm veranschaulicht die automatische Speicherdauer für eine Referenz und einen Zeiger im globalen Geltungsbereich.

#einschließen
Verwenden von Namespace-Std;
intx = 1;
int&m = x;
Zeichen y = 'A';
char*n = &y;
int main()

cout << m << *n << '\n';
0 zurückgeben;

Die Ausgabe ist, 1A .

Die Dauer von m beginnt bei „int& m = x;“ und endet am Ende des Programms. Die Dauer von n beginnt bei „char* n = &y;“ und endet am Ende des Programms.

Dynamische Speicherdauer

Kostenloser Shop

Auf einem modernen Computer können mehrere Programme gleichzeitig ausgeführt werden. Jedes Programm hat seinen eigenen Speicherbereich. Der Rest des Speichers, der von keinem Programm verwendet wird, wird als freier Speicher bezeichnet. Der folgende Ausdruck wird verwendet, um eine Position für eine Ganzzahl aus dem freien Speicher zurückzugeben

neue int

Dieser Ort (Speicher) für die zurückgegebene Ganzzahl muss noch durch Zuweisung an einen Zeiger identifiziert werden. Der folgende Code veranschaulicht, wie der Zeiger mit kostenlosem Speicher verwendet wird:

int *ptrInt = neues int;
*ptrInt = 12;
cout<< *ptrInt <<'\n';

Die Ausgabe ist 12 .

Um die Lebensdauer des Objekts zu beenden, verwenden Sie den Löschausdruck wie folgt:

ptrInt löschen;

Das Argument für den Löschausdruck ist ein Zeiger. Der folgende Code veranschaulicht seine Verwendung:

int *ptrInt = neues int;
*ptrInt = 12;
ptrInt löschen;

Ein mit dem neuen Ausdruck erstellter und mit dem Löschausdruck gelöschter Zeiger hat eine dynamische Speicherdauer. Dieser Zeiger stirbt, wenn er den Gültigkeitsbereich verlässt oder gelöscht wird. Die Dauer des Objekts im vorherigen Code beginnt bei „*ptrInt = 12;“ und endet am Ende des deklarativen Bereichs (Geltungsbereich). Es gibt mehr zu den new- und delete-Ausdrücken, als hier besprochen wurde - siehe später.

Statische Speicherdauer

Statisches Objekt

Ein als statisch deklariertes Objekt verhält sich wie ein gewöhnliches Objekt, außer dass seine Speicherdauer von der Initialisierung bis zum Ende des Programms beginnt. Es kann nicht außerhalb seines Geltungsbereichs gesehen werden, aber es kann indirekt von außerhalb seines Geltungsbereichs verwendet werden.

Betrachten Sie das folgende Programm, das von 1 bis 5 zählen soll (Testen Sie das Programm nicht) :

#einschließen
Verwenden von Namespace-Std;
int fn()

int stc = 1;
cout << " << stc;
stc = stc + 1;
wenn (stc > 5)
0 zurückgeben;
fn();

int main()

fn();
0 zurückgeben;

Die Ausgabe ist 1 1 1 1 1 1 1 1… und endet nie wirklich. Die Funktionsdefinition ist eine wiederkehrende Funktion; Das heißt, es ruft sich selbst weiter auf, bis eine Bedingung erfüllt ist.

Die Lösung besteht darin, das stc-Objekt statisch zu machen. Nachdem ein statisches Objekt initialisiert wurde, kann sein Wert nicht mehr geändert werden, bis das Programm beendet ist. Das folgende Programm (das Sie testen können), das das gleiche ist wie das obige, aber jetzt mit stc statisch gemacht, zählt von 1 bis 5 :

#einschließen
Verwenden von Namespace-Std;
int fn()

statisch int stc = 1;
cout << " << stc;
stc = stc + 1;
wenn (stc > 5)
0 zurückgeben;
fn();

int main()

fn();
0 zurückgeben;

Die Ausgabe ist: 1 2 3 4 5 .

Hinweis: Die Dauer eines statischen Objekts beginnt mit der Initialisierung des Objekts und endet mit dem Programmende. In der Zwischenzeit kann das Objekt indirekt aus einem anderen Umfang verwendet werden. Nachdem ein statisches Objekt initialisiert wurde, kann sein Anfangswert nicht mehr geändert werden, selbst wenn seine Definition neu bewertet wird. Im obigen Code wird der stc nicht zurückgesetzt, wenn er das nächste Mal aufgerufen wird. Beim nächsten Aufruf wird es um „stc = stc + 1;“ erhöht.

Statische Daten Mitglied

Ein Satz zusammengehöriger Variablen und Funktionen kann in eine verallgemeinerte Einheit, die als Klasse bezeichnet wird, zusammengefasst werden. Wenn den Variablen bestimmte Werte zugewiesen werden, wird die Klasse zu einem Objekt. Ein Objekt wird jedoch nicht erstellt, indem man der Variablen nur Werte zuweist. Die Klasse wird instanziiert, um ein Objekt zu erhalten; und jedes erstellte Objekt hat seinen eigenen Namen, der sich von anderen Objekten derselben Klasse unterscheidet. Das folgende Programm zeigt eine Klasse namens TheCla und ein Objekt namens obj; es zeigt auch, wie das Objekt instanziiert und in der main()-Funktion verwendet wird:

#einschließen
Verwenden von Namespace-Std;
Klasse TheCla

Öffentlichkeit:
int-Zahl;
void func (char cha, const char *str)

cout << "There are " << num << " books worth " << cha << str << " in the store." << '\n';

;
int main()

TheCla obj;
obj.Anzahl = 12;
obj.func('$', "500");
0 zurückgeben;

Die Ausgabe ist:

Es gibt 12 Bücher im Wert von 500 $ im Laden.

Beachten Sie, dass um der Variablen num den Wert 12 zuzuweisen, das Objekt instanziiert werden muss, bevor die Zuweisung erfolgen kann. Es ist dem Programmierer möglich, den Wert zuzuweisen, ohne ein Objekt zu instanziieren (erzeugen). Um dies zu erreichen, muss die Variable num als static deklariert werden. Dann wird es als „TheCla::num“ ohne den Objektnamen, aber mit dem Klassennamen aufgerufen. Das folgende Programm veranschaulicht dies:

#einschließen
Verwenden von Namespace-Std;
Klasse TheCla

Öffentlichkeit:
statische const int num = 12;
void func (char cha, const char *str)

cout << "There are " << num << " books worth " << cha << str << " in the store." << '\n';

;
int main()

cout << TheCla::num << '\n';
TheCla obj;
obj.func('$', "500");
0 zurückgeben;

Die Ausgabe ist:

12
Es gibt 12 Bücher im Wert von 500 $ im Laden.

Beachten Sie, dass für den Zugriff auf das Datenelement num in main() der Bereichsauflösungsoperator :: verwendet werden musste. Auch nicht, dass die Variable num konstant gemacht und in der Klassenbeschreibung (Definition) initialisiert werden musste.

Statische Elementfunktion

Beachten Sie, dass in der vorherigen Programmauflistung oben ein Objekt instanziiert werden musste, um die Funktion func in main() verwenden zu können. Der Programmierer kann die Funktion aufrufen, ohne ein Objekt zu instanziieren (erstellen). Um dies zu erreichen, muss der Funktionsdefinition das Wort „statisch“ vorangestellt werden. Dann wird es als „TheCla::func()“ ohne den Objektnamen, aber mit dem Klassennamen aufgerufen. Das folgende Programm veranschaulicht dies für statische Datenmember und statische Memberfunktionen:

#einschließen
Verwenden von Namespace-Std;
Klasse TheCla

Öffentlichkeit:
statische const int num = 12;
static void func (char cha, const char *str)

cout << "There are " << num << " books worth " << cha << str << " in the store." << '\n';

;
int main()

TheCla::func('$', "500");
0 zurückgeben;

Die Ausgabe ist:

Es gibt 12 Bücher im Wert von 500 $ im Laden.

Thread-Speicherdauer

Thread als Feature in C++, wurde noch nicht vom g++-Compiler implementiert. Anstatt dies zu erklären, wird das Zitat aus der C++-Spezifikation wie folgt angegeben:

  1. Alle mit dem Schlüsselwort thread_local deklarierten Variablen haben eine Thread-Speicherdauer. Die Speicherung dieser Entitäten erfolgt für die Dauer des Threads, in dem sie erstellt wurden. Es gibt ein eindeutiges Objekt oder eine Referenz pro Thread, und die Verwendung des deklarierten Namens bezieht sich auf die Entität, die mit dem aktuellen Thread verknüpft ist.
  2. Eine Variable mit Thread-Speicherdauer muss vor ihrer ersten Verwendung im Odr initialisiert und, wenn sie erstellt wurde, beim Thread-Ausgang vernichtet werden.”

Fazit

Die Lebensdauer eines Objekts beginnt, wenn seine Initialisierung abgeschlossen ist, und endet, wenn sein Speicher freigegeben wird. Die Dauer des dynamischen Speichers beginnt, wenn der von (neuer Typ) erstellte Speicher initialisiert wird, und endet, wenn das Objekt den Gültigkeitsbereich verlässt oder durch "Löschen-Zeiger" gelöscht wird. Die Dauer eines statischen Objekts beginnt mit der Initialisierung des Objekts und endet mit dem Programmende. Nachdem ein statisches Objekt initialisiert wurde, kann sein Anfangswert nicht mehr geändert werden, selbst wenn seine Definition neu bewertet wird. Auf statische Datenmember und statische Funktionsmember wird außerhalb der Klassenbeschreibung mit „ClassName::name“ zugegriffen.

Chrys

OpenTTD vs. Simutrans
Das Erstellen einer eigenen Transportsimulation kann Spaß machen, entspannend und äußerst verlockend sein. Deshalb sollten Sie so viele Spiele wie mög...
OpenTTD-Tutorial
OpenTTD ist eines der beliebtesten Wirtschaftssimulationsspiele auf dem Markt. In diesem Spiel musst du ein wunderbares Transportunternehmen aufbauen....
SuperTuxKart für Linux
SuperTuxKart ist ein großartiger Titel, der entwickelt wurde, um Ihnen das Mario Kart-Erlebnis kostenlos auf Ihrem Linux-System zu bieten. Es ist ziem...