switch
statement
Überträgt die Steuerung an eine von mehreren Anweisungen, abhängig vom Wert einer Bedingung.
Inhaltsverzeichnis |
Syntax
attr
(optional)
switch
(
init-statement
(optional)
condition
)
statement
|
|||||||||
| attr | - | (since C++11) beliebige Anzahl von Attributen | ||
| init-statement | - |
(since C++17)
eines der folgenden Elemente:
Beachten Sie, dass jede init-statement mit einem Semikolon enden muss. Dies ist der Grund, warum sie informell oft als ein Ausdruck oder eine Deklaration gefolgt von einem Semikolon beschrieben wird. |
||
| condition | - | eine Bedingung | ||
| statement | - | eine Anweisung (typischerweise eine zusammengesetzte Anweisung) |
Bedingung
Eine Bedingung kann entweder ein Ausdruck oder eine einfache Deklaration sein.
|
(seit C++26) |
- Wenn es syntaktisch als Ausdruck aufgelöst werden kann, wird es als Ausdruck behandelt. Andernfalls wird es als Deklaration behandelt die keine strukturierte Bindungsdeklaration ist (seit C++26) .
Wenn die Steuerung die Bedingung erreicht, ergibt die Bedingung einen Wert, der verwendet wird, um zu bestimmen, zu welchem Label die Steuerung gehen wird.
Ausdruck
Wenn condition ein Ausdruck ist, ist der von ihm gelieferte Wert der Wert des Ausdrucks.
Deklaration
Wenn condition eine einfache Deklaration ist, ist der von ihr gelieferte Wert der Wert der Entscheidungsvariablen (siehe unten).
Nicht-strukturierte Bindungsdeklaration
Die Deklaration unterliegt folgenden Einschränkungen:
- Syntaktisch entspricht es der folgenden Form:
|
(bis C++11) |
|
(seit C++11) |
- Der Deklarator darf keinen function oder kein array spezifizieren.
- Die type specifier sequence (bis C++11) declaration specifier sequence darf nur Typspezifizierer und constexpr enthalten, und sie (seit C++11) darf keine class oder enumeration definieren.
Die Entscheidungsvariable der Deklaration ist die deklarierte Variable.
Strukturierte BindungsdeklarationDie Deklaration unterliegt folgenden Einschränkungen:
Die Entscheidungsvariable der Deklaration ist die eingeführte Variable e , die durch die Deklaration eingeführt wird . |
(seit C++26) |
Typ
condition kann nur die folgenden Typen ergeben:
- Ganzzahlige Typen
- Aufzählungstypen
- Klassentypen
Wenn der gelieferte Wert von einem Klassentyp ist, wird er kontextuell implizit in einen integralen oder Aufzählungstyp konvertiert.
Wenn der (möglicherweise konvertierte) Typ integral promotions unterliegt, wird der resultierende Wert in den höherwertigen Typ konvertiert.
Labels
Jede Anweisung innerhalb der switch -Anweisung kann mit einer oder mehreren der folgenden Bezeichnungen versehen werden:
attr
(optional)
case
constant-expression
:
|
(1) | ||||||||
attr
(optional)
default:
|
(2) | ||||||||
| attr | - | (seit C++11) beliebig viele Attribute |
| constant-expression | - | ein konvertierter konstanter Ausdruck des angepassten Typs der switch -Bedingung |
Ein
case
- oder
default
-Label ist mit der innersten
switch
-Anweisung verknüpft, die es umschließt.
Wenn eine der folgenden Bedingungen erfüllt ist, ist das Programm fehlerhaft:
- Eine switch -Anweisung ist mit mehreren case -Labels verknüpft, deren constant-expression s nach Konvertierungen denselben Wert haben.
- Eine switch -Anweisung ist mit mehreren default -Labels verknüpft.
Kontrollflussübertragung
Wenn die Bedingung einer switch -Anweisung einen (möglicherweise konvertierten) Wert ergibt:
- Wenn eine der zugehörigen case Label-Konstanten denselben Wert hat, wird die Steuerung an die Anweisung übergeben, die durch das übereinstimmende case Label gekennzeichnet ist.
- Andernfalls, wenn ein zugehöriges default Label vorhanden ist, wird die Steuerung an die Anweisung übergeben, die durch das default Label gekennzeichnet ist.
- Andernfalls wird keine der Anweisungen in der switch Anweisung ausgeführt.
case und default Labels an sich verändern den Kontrollfluss nicht. Um eine switch -Anweisung in der Mitte zu verlassen, siehe break -Anweisungen .
Compiler können Warnungen zu Fallthrough (Erreichen des nächsten
case
- oder
default
-Labels ohne einen
break
)
ausgeben, es sei denn, das Attribut
[[
fallthrough
]]
erscheint unmittelbar vor dem
case
-Label, um anzuzeigen, dass der Fallthrough beabsichtigt ist
(seit C++17)
.
|
switch Anweisungen mit InitialisiererFalls init-statement verwendet wird, entspricht die switch-Anweisung:
Mit der Ausnahme, dass Namen, die durch den init-statement deklariert werden (falls init-statement eine Deklaration ist) und Namen, die durch condition deklariert werden (falls condition eine Deklaration ist), sich im selben Gültigkeitsbereich befinden, welcher auch der Gültigkeitsbereich von statement ist. |
(seit C++17) | |||||||||||||||||||||||
Hinweise
Da die Übertragung der Kontrolle nicht erlaubt ist, in den Geltungsbereich einer Variable einzutreten, muss eine Deklarationsanweisung, die innerhalb der Anweisung angetroffen wird, in ihrer eigenen zusammengesetzten Anweisung geschachtelt werden:
Schlüsselwörter
Beispiel
Der folgende Code zeigt mehrere Anwendungsfälle der switch -Anweisung:
#include <iostream> int main() { const int i = 2; switch (i) { case 1: std::cout << '1'; case 2: // Ausführung beginnt bei diesem case-Label std::cout << '2'; case 3: std::cout << '3'; [[fallthrough]]; // C++17-Attribut zur Unterdrückung der Fallthrough-Warnung case 5: std::cout << "45"; break; // Ausführung nachfolgender Anweisungen wird beendet case 6: std::cout << '6'; } std::cout << '\n'; switch (i) { case 4: std::cout << 'a'; default: std::cout << 'd'; // es gibt keine anwendbaren konstanten Ausdrücke // daher wird default ausgeführt } std::cout << '\n'; switch (i) { case 4: std::cout << 'a'; // nichts wird ausgeführt } // wenn Aufzählungen in einer switch-Anweisung verwendet werden, geben // viele Compiler Warnungen aus, wenn einer der Enumeratoren nicht behandelt wird enum color { RED, GREEN, BLUE }; switch (RED) { case RED: std::cout << "red\n"; break; case GREEN: std::cout << "green\n"; break; case BLUE: std::cout << "blue\n"; break; } // die C++17 Init-Statement-Syntax kann hilfreich sein, wenn keine // implizite Konvertierung zu integralem oder Aufzählungstyp vorhanden ist struct Device { enum State { SLEEP, READY, BAD }; auto state() const { return m_state; } /* ... */ private: State m_state{}; }; switch (auto dev = Device{}; dev.state()) { case Device::SLEEP: /* ... */ break; case Device::READY: /* ... */ break; case Device::BAD: /* ... */ break; } // pathologische Beispiele // die Anweisung muss kein zusammengesetzter Ausdruck sein switch (0) std::cout << "this does nothing\n"; // Labels erfordern ebenfalls keinen zusammengesetzten Ausdruck switch (int n = 1) case 0: case 1: std::cout << n << '\n'; }
Ausgabe:
2345 d red 1
Fehlerberichte
Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | Angewendet auf | Verhalten wie veröffentlicht | Korrektes Verhalten |
|---|---|---|---|
| CWG 1767 | C++98 |
condition
s von Typen, die nicht für
integrale Promotion geeignet waren, konnten nicht gepromotet werden |
keine Promotion von
condition s dieser Typen durchführen |
| CWG 2629 | C++98 | condition konnte eine Deklaration einer Gleitkommavariable sein | verboten |
Siehe auch
|
C-Dokumentation
für
switch
|
Externe Links
| 1. | Schleifenabrollung mit Duff's Device |
| 2. | Duff's Device kann zur Implementierung von Coroutinen in C/C++ verwendet werden |