C++ Tutorial

 Daten Lebensdauer & Sichtbarkeit

Lebensdauer

Die Lebensdauer eines Datums, und damit auch dessen Sichtbarkeit, hängt u.a. von der Stelle ab, an der das Datum definiert ist.

Modul

Ein Datum, welches nicht innerhalb eines Blocks {...} definiert ist, wird als globales Datum bezeichnet. Es ist ab der Stelle im Programm gültig, an dem es definiert ist. Seine Gültigkeit endet am Modulende (Dateiende). Eine globale Variable wird vor dem Eintritt in die main() Funktion mit 0 initialisiert.

Funktion

Ein Datum, das innerhalb einer Funktionen (wie z.B. innerhalb von main()) definiert ist, wird als lokales Datum bezeichnet. Ein lokales Datum ist nur in der Funktion gültig, in der es definiert ist. Es wird nicht automatisch initialisiert und hat damit zu Beginn einen zufälligen Inhalt.

Block

Ein Datum, das innerhalb eines Blocks {...} definiert ist, verhält sich wie ein lokales Datum. D.h., es wird nicht automatisch initialisiert und verliert beim Verlassen des Blocks seine Gültigkeit.

Zugriff auf globale Daten (Gültigkeitsbereichsoperator)

Wird ein globales Datum durch ein funktions- oder blocklokales Datum verdeckt, kann mithilfe des Gültigkeitsbereichsoperators :: (scope resolution operator, das sind zwei Doppelpunkte!) vor dem Variablennamen auf das globale Datum zugegriffen werden.

#include <iostream>
#include <format>

// Daten mit Modul-Lebensdauer
int ivar1;

void PrintIVar1()
{
   // Lokales Datum
   int counter = 1;
   // Lokales und globales Datum ausgeben
   std::cout << std::format("{}. Aufruf: ivar1={}\n", counter,ivar1);
}

void PrintIntData(int val)
{
   // Gibt lokales Datum (Parameter) aus
   std::cout << std::format("int-Datum = {}\n", val);
}

int main()
{
   ivar1 = 10;       // Globales Datum setzen
   PrintIVar1();

   // Schleifenzaehler ivar1 ist nur im for-Block gueltig
   // und 'ueberschreibt' das gleichnamige globale Datum
   for (int ivar1 = 0; ivar1 < 3; ivar1++)
   {
      if (ivar1 != 1)
         PrintIntData(ivar1);      // Gibt lokales ivar1 aus
      else
         PrintIntData(::ivar1);    // Gibt globales ivar1 aus
    }
}

Spezifizierer

Um einem Datum eine vom Standard abweichende Sichtbarkeit bzw. Lebensdauer zuzuweisen, wird vor dem Datentyp des Datums einer der nachfolgenden Spezifizierer angegeben.

Speicherklasse extern

Ein Datum oder eine Funktion der Speicherklasse extern teilt dem Compiler mit, dass seine Definition in einem anderen Modul (Quellcode-Datei) erfolgt als im aktuellen.

Eine etwas andere Wirkung besitzt die Speicherklasse extern bei einer benannten Konstante. Soll eine benannte Konstante in verschiedenen Modulen verwendet werden, muss sie sowohl bei ihrer Definition als auch bei den Verweisen darauf als externe Konstante definiert werden. Hierbei ist zu beachten, dass die Konstante nur einmal initialisiert werden darf.

// Datei1.cpp
#include <iostream>
#include <format>

// Globale int-Variable
int ivar = 10;
// Konstante ist in einer anderen Quellcode-Datei definiert
// und darf daher nicht initialisiert werden
extern const int CIVAR;

// Funktion AnyFunc ist in einer anderen Quellcode-Datei definiert
extern void AnyFunc();

int main()
{
   // Ausgabe der Daten
   std::cout << std::format("main: ivar = {}, civar = {}\n", ivar, CIVAR);
   // Aufruf der externen Funktion AnyFunc()
   AnyFunc();
}
// Datei2.cpp
#include <iostream>
#include <format>

// ivar ist in einer anderen Quellcode-Datei definiert
extern int ivar;
// Globale Konstante, muss bei der Definition ebenfalls als
// extern definiert werden, damit von anderen Quellcode-Dateien
// darauf zugegriffen werden kann.
extern const int CIVAR = 100;

// Globale Funktion, wird von main() aufgerufen
void AnyFunc()
{
   std::cout << std::format("AnyFunc: ivar = {}, civar = {}\n", ivar, CIVAR);
}

Speicherklasse static

Ein globales Datum oder eine Funktion der Speicherklasse static ist nur in dem Modul sichtbar, in dem die Definition erfolgt.

Ein lokales Datum der Speicherklasse static behält seinen letzten Wert auch dann bei, wenn sein Gültigkeitsbereich verlassen wird, d.h., es wird beim Verlassen des Gültigkeitsbereichs nicht gelöscht. Auf das statische Datum kann aber weiterhin nur innerhalb dessen Gültigkeitsbereich zugegriffen werden.

#include <iostream>
#include <format>

// Globale Variable ivar ist nur in dieser Quellcode-Datei sichtbar
static int ivar;

// Funktion zur Ausgabe einer Seitenzahl
void PrintFooter()
{
   // Statische Variable fuer die Seitenzahl
   static unsigned short page = 1;
   // Seitenzahl ausgeben
   std::cout << std::format("Seite {}\n", page);
   // Seitenzahl erhoehen
   page++;
}

int main()
{
   // Einige Seitenzahlen ausgeben
   for (ivar = 0; ivar<3; ivar++)
      PrintFooter();
}

Speicherklasse mutable

Die mutable Speicherklasse spielt nur im Zusammenhange mit Klassen eine Rolle und ist nur der Vollständigkeit halber hier erwähnt. Mehr dazu später bei der Einführung von Klassen.

Qualifizierer const

Der const Qualifizierer kennzeichnet u.a. ein Datum, das nach seiner Definition nicht mehr veränderbar ist (siehe auch Kapitel Daten).

Später werden wir uns diesen Qualifizierer nochmals ansehen, und zwar im Zusammenhang mit Klassen.

Qualifizierer volatile

Ein als volatile definiertes Datum teilt dem Compiler mit, dass sein Inhalt auch außerhalb des 'normalen' Programmablaufes verändert werden kann. D.h., der Compiler darf keine Optimierung bezüglich des Inhalts des Datums vornehmen. Typische volatile Daten sind Daten die vom Betriebssystem bereitgestellt werden (z.B. die Systemzeit) oder in Interrupt-Routinen verändert werden.