switch
statement
Transfère le contrôle à l'une des plusieurs instructions, en fonction de la valeur d'une condition.
Table des matières |
Syntaxe
attr
(optionnel)
switch
(
init-statement
(optionnel)
condition
)
statement
|
|||||||||
| attr | - | (depuis C++11) n'importe quel nombre d' attributs | ||
| init-statement | - |
(depuis C++17)
l'un des éléments suivants :
Notez que toute init-statement doit se terminer par un point-virgule. C'est pourquoi elle est souvent décrite informellement comme une expression ou une déclaration suivie d'un point-virgule. |
||
| condition | - | une condition | ||
| statement | - | une instruction (généralement une instruction composée) |
Condition
Une condition peut être soit une expression soit une déclaration simple .
|
(depuis C++26) |
- S'il peut être résolu syntaxiquement comme une expression, il est traité comme une expression. Sinon, il est traité comme une déclaration qui n'est pas une déclaration de décomposition structurée (depuis C++26) .
Lorsque le contrôle atteint la condition, celle-ci produira une valeur, qui est utilisée pour déterminer vers quelle étiquette le contrôle se dirigera.
Expression
Si condition est une expression, la valeur qu'elle produit est la valeur de l'expression.
Déclaration
Si condition est une déclaration simple, la valeur qu'elle produit est la valeur de la variable de décision (voir ci-dessous).
Déclaration non structurée de liaison
La déclaration comporte les restrictions suivantes :
- Conforme syntaxiquement à la forme suivante :
|
(jusqu'en C++11) |
|
(depuis C++11) |
- Le déclarateur ne peut pas spécifier une fonction ou un tableau .
- La séquence de spécificateurs de type (jusqu'en C++11) séquence de spécificateurs de déclaration ne peut contenir que des spécificateurs de type et constexpr , et elle (depuis C++11) ne peut pas définir une classe ou une énumération .
La variable de décision de la déclaration est la variable déclarée.
Déclaration de liaison structuréeLa déclaration présente les restrictions suivantes :
La variable de décision de la déclaration est la variable inventée e introduite par la déclaration . |
(depuis C++26) |
Type
condition ne peut produire que les types suivants :
- types intégraux
- types énumérés
- types de classe
Si la valeur produite est d'un type classe, elle est implicitement convertie contextuellement en un type intégral ou énumération.
Si le type (éventuellement converti) est soumis aux promotions intégrales , la valeur obtenue est convertie vers le type promu.
Étiquettes
Toute instruction au sein de l'instruction switch peut être étiquetée avec une ou plusieurs des étiquettes suivantes :
attr
(optionnel)
case
constant-expression
:
|
(1) | ||||||||
attr
(optionnel)
default:
|
(2) | ||||||||
| attr | - | (depuis C++11) n'importe quel nombre d' attributs |
| constant-expression | - | une expression constante convertie du type ajusté de la condition switch |
Une
case
ou une étiquette
default
est associée à l'instruction
switch
la plus imbriquée qui l'encadre.
Si l'une des conditions suivantes est satisfaite, le programme est mal formé :
- Une instruction switch est associée à plusieurs étiquettes case dont les expressions-constantes ont la même valeur après conversions.
- Une instruction switch est associée à plusieurs étiquettes default .
Transfert du flux de contrôle
Lorsque la condition d'une instruction switch produit une valeur (éventuellement convertie) :
- Si l'une des constantes d'étiquette case associées a la même valeur, le contrôle est transféré à l'instruction étiquetée par l'étiquette case correspondante.
- Sinon, s'il existe une étiquette default associée, le contrôle est transféré à l'instruction étiquetée par l'étiquette default .
- Sinon, aucune des instructions dans l'instruction switch ne sera exécutée.
case et default labels en eux-mêmes n'altèrent pas le flux de contrôle. Pour sortir d'une instruction switch depuis le milieu, voir les break statements .
Les compilateurs peuvent émettre des avertissements en cas de fallthrough (atteindre l'étiquette
case
ou
default
suivante sans
break
)
sauf si l'attribut
[[
fallthrough
]]
apparaît immédiatement avant l'étiquette
case
pour indiquer que le fallthrough est intentionnel
(depuis C++17)
.
|
switch instructions avec initialiseurSi une instruction-init est utilisée, l'instruction switch est équivalente à
Sauf que les noms déclarés par l' instruction-init (si l' instruction-init est une déclaration) et les noms déclarés par la condition (si la condition est une déclaration) sont dans la même portée, qui est également la portée de l' instruction . |
(depuis C++17) | |||||||||||||||||||||||
Notes
Parce que le transfert de contrôle n'est pas autorisé à entrer dans la portée d'une variable, si une instruction de déclaration est rencontrée à l'intérieur de la statement , elle doit être délimitée dans son propre bloc composé :
Mots-clés
Exemple
Le code suivant montre plusieurs cas d'utilisation de l'instruction switch :
#include <iostream> int main() { const int i = 2; switch (i) { case 1: std::cout << '1'; case 2: // l'exécution commence à cette étiquette case std::cout << '2'; case 3: std::cout << '3'; [[fallthrough]]; // attribut C++17 pour supprimer l'avertissement sur le fallthrough case 5: std::cout << "45"; break; // l'exécution des instructions suivantes est terminée case 6: std::cout << '6'; } std::cout << '\n'; switch (i) { case 4: std::cout << 'a'; default: std::cout << 'd'; // il n'y a pas d'expressions constantes applicables // donc default est exécuté } std::cout << '\n'; switch (i) { case 4: std::cout << 'a'; // rien n'est exécuté } // lorsque des énumérations sont utilisées dans une instruction switch, de nombreux compilateurs // émettent des avertissements si l'un des énumérateurs n'est pas géré 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; } // la syntaxe d'instruction d'initialisation de C++17 peut être utile lorsqu'il n'y a // pas de conversion implicite vers un type intégral ou d'énumération 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; } // exemples pathologiques // l'instruction ne doit pas nécessairement être une instruction composée switch (0) std::cout << "this does nothing\n"; // les étiquettes ne nécessitent pas non plus une instruction composée switch (int n = 1) case 0: case 1: std::cout << n << '\n'; }
Sortie :
2345 d red 1
Rapports de défauts
Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.
| DR | Appliqué à | Comportement tel que publié | Comportement correct |
|---|---|---|---|
| CWG 1767 | C++98 |
condition
s de types non soumis à
la promotion entière ne pouvaient pas être promues |
ne pas promouvoir
condition s de ces types |
| CWG 2629 | C++98 | condition pouvait être une déclaration d'une variable à virgule flottante | interdit |
Voir aussi
|
Documentation C
pour
switch
|
Liens externes
| 1. | Déroulage de boucle utilisant le Dispositif de Duff |
| 2. | Le dispositif de Duff peut être utilisé pour implémenter des coroutines en C/C++ |