Was eine Variable ist
Eine Variable ist ein benannter Speicherbereich, der einen Wert enthält. In C++ hat jede Variable einen festen Typ - festgelegt bei der Deklaration -, und dieser Typ ändert sich nie. Das macht C++ statisch typisiert: Der Compiler kennt den Typ jeder Variable, bevor das Programm läuft, und weigert sich, Code zu kompilieren, der einen Wert der falschen Art speichert.
Eine Deklaration besteht aus drei Teilen: dem Typ, dem Namen und (fast immer) einem Anfangswert.
Lies int age = 30; als „erstelle einen int namens age und lege 30 hinein". Das Semikolon beendet die Anweisung, genau wie die Seite zu Kommentaren für jede Anweisung gezeigt hat. Beachte, dass isActive als 1 ausgegeben wurde: Ein bool wird standardmäßig als 1/0 angezeigt - darauf baut die Seite zu den Datentypen auf.
Initialisierung vs. Zuweisung
Diese beiden sehen ähnlich aus, sind aber unterschiedliche Operationen, und dieser Unterschied ist eine der wichtigsten Ideen auf dieser Seite.
Die Initialisierung gibt einer Variable als Teil der Deklaration ihren ersten Wert. Die Zuweisung ändert den Wert einer bereits existierenden Variable.
Du kannst ohne Initialisierung deklarieren und später zuweisen, aber sei vorsichtig:
Das funktioniert, weil wir score zugewiesen haben, bevor wir es gelesen haben. Die gefährliche Variante ist, es zuerst zu lesen - das kommt als Nächstes.
Die Falle der nicht initialisierten Variable
Das ist die klassische C++-Falle, die es in vielen anderen Sprachen nicht gibt. Das Lesen einer lokalen Variable, die deklariert wurde, aber nie einen Wert bekommen hat, ist undefiniertes Verhalten: Die Variable enthält die Bytes, die zufällig in diesem Speicher lagen.
int score; // nicht initialisiert
std::cout << score; // undefiniertes Verhalten - gibt Müll aus, oder „funktioniert", oder stürzt ab
Der Compiler baut das anstandslos. Es kann 0 ausgeben, es kann 32766 ausgeben, und es kann sich bei jedem Lauf oder auf jeder Maschine anders verhalten - was diese Bugs zur Qual macht, wenn man sie aufspüren will. Zwei Verteidigungen:
- Initialisiere immer bei der Deklaration.
int score = 0;kostet nichts und beseitigt das gesamte Problem. - Schalte Warnungen ein. Das Kompilieren mit
-Wall -Wextralässt den Compiler viele nicht initialisierte Lesezugriffe melden, bevor sie dir schaden.
Bevorzuge für jede lokale Variable die erste Option: gib ihr einen sinnvollen Startwert in dem Moment, in dem du sie erstellst.
Initialisierungsstile: =, () und {}
C++ bietet dir mehrere Möglichkeiten, einen Anfangswert zu schreiben. Meist tun sie dasselbe, aber die Klammer-Initialisierung hat ein zusätzliches Sicherheitsmerkmal, das man kennen sollte.
Der Grund, zu {} zu greifen, ist, dass es verengende Umwandlungen (narrowing) ablehnt - Zuweisungen, die stillschweigend Daten verlieren würden. Mit = wird ein gebrochener Wert lautlos abgeschnitten; mit {} stoppt dich der Compiler:
int x = 3.9; // kompiliert - x wird stillschweigend 3 (die .9 wird verworfen)
int y{3.9}; // Kompilierfehler - die Verengung von double zu int ist nicht erlaubt
Das zur Kompilierzeit abzufangen ist genau das, was du willst. Eine gängige moderne Gewohnheit ist, für diese zusätzliche Prüfung standardmäßig {} zu verwenden und nur dann auf = zurückzugreifen, wenn sich die Kopier-Initialisierung natürlicher liest.
Namensregeln und Konventionen
C++ erzwingt ein paar harte Regeln, und alle setzen dann Konventionen darauf. Die Regeln: Ein Name darf Buchstaben, Ziffern und _ enthalten; er darf nicht mit einer Ziffer beginnen; er darf kein reserviertes Schlüsselwort sein (wie int oder return); und er unterscheidet Groß- und Kleinschreibung (age und Age sind zwei verschiedene Variablen). Vermeide Namen, die mit einem Unterstrich gefolgt von einem Großbuchstaben beginnen oder die zwei Unterstriche hintereinander enthalten - diese sind für die Implementierung reserviert.
Die Konventionen, denen der meiste C++-Code folgt:
- Variablen verwenden
snake_caseodercamelCase- wähle eines und bleib konsistent:item_countoderitemCount. - Namen sollten den Wert beschreiben:
count, nichtc;user_email, nichtx.
Klare Namen sind keine Verzierung - sie sind die Art, wie dein zukünftiges Ich den Code liest. total_price = item_count * price_per_item erklärt sich auf eine Weise von selbst, die t = c * p niemals erreichen wird.
Gültigkeitsbereich von Variablen
Eine Variable existiert nur innerhalb des Blocks - der { ... } -, in dem sie deklariert wird, und sie wird bei der schließenden Klammer zerstört. Das ist ihr Gültigkeitsbereich (scope). Eine in einer Schleife oder einem if-Block deklarierte Variable ist außerhalb davon unsichtbar:
Sowohl i als auch square gehören zur Schleife und verschwinden, wenn sie endet; total ist im äußeren Block deklariert, also überlebt es. Ein innerer Block kann einen Namen aus einem äußeren Block auch verdecken (shadow): Eine neue Variable mit demselben Namen verbirgt die äußere vorübergehend, bis der innere Block schließt - eine häufige Quelle der Verwirrung. Vermeide es daher, Namen über verschachtelte Gültigkeitsbereiche hinweg wiederzuverwenden.
Die praktische Erkenntnis: Deklariere jede Variable im kleinsten Block, der sie braucht, und initialisiere sie dort. Ein enger Gültigkeitsbereich bedeutet weniger Namen, die um deine Aufmerksamkeit konkurrieren, und weniger Gelegenheiten, einen Wert weit entfernt von der Stelle zu lesen, an der er gesetzt wurde.
Als Nächstes: Datentypen
Jede Variable auf dieser Seite begann mit einem Typ - int, double, string, bool. Die nächste Seite schlüsselt die Datentypen von C++ im Detail auf: die fundamentalen Typen und ihre Größen, vorzeichenbehaftete vs. vorzeichenlose Ganzzahlen, float vs. double, char und wie man den richtigen Typ für die Aufgabe wählt.
Häufig gestellte Fragen
Wie deklariert man eine Variable in C++?
Schreibe den Typ, dann einen Namen und optional einen Wert: int age = 30;. Der Typ (int) ist über die gesamte Lebensdauer der Variable festgelegt; der Name (age) ist die Art, wie du auf sie verweist. Du kannst sie auch ohne Wert deklarieren - int age; -, aber bei einer lokalen Variable bleibt sie dann mit Müll gefüllt, bis du ihr einen Wert zuweist. Initialisiere sie deshalb immer direkt bei der Deklaration.
Was ist der Unterschied zwischen Initialisierung und Zuweisung in C++?
Die Initialisierung gibt einer Variable als Teil ihrer Deklaration ihren ersten Wert: int x = 5; oder int x{5};. Die Zuweisung ändert den Wert einer bereits existierenden Variable: x = 7;. Der Unterschied ist wichtig, denn das Lesen einer lokalen Variable, die zwar deklariert, aber nie initialisiert wurde, ist undefiniertes Verhalten.
Was passiert, wenn man in C++ eine nicht initialisierte Variable verwendet?
Das Lesen des Werts einer nicht initialisierten lokalen Variable ist undefiniertes Verhalten (undefined behavior): Die Variable enthält die Bytes, die zufällig schon in diesem Speicher lagen, also kann dein Programm eine Zufallszahl ausgeben, durch Glück funktionieren oder abstürzen. Der Compiler hält dich nicht auf (auch wenn viele mit -Wall warnen), daher ist die Lösung, lokalen Variablen bei der Deklaration immer einen Wert zu geben.