Namespaces
Variants

switch statement

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
switch
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Transfiere el control a una de varias sentencias, dependiendo del valor de una condición.

Contenidos

Sintaxis

attr  (opcional) switch ( init-statement  (opcional) condition ) statement
attr - (desde C++11) cualquier número de atributos
init-statement - (desde C++17) cualquiera de los siguientes:
(desde C++23)

Nótese que cualquier init-statement debe terminar con un punto y coma. Por esto se describe informalmente como una expresión o una declaración seguida de un punto y coma.

condition - una condición
statement - una sentencia (típicamente una sentencia compuesta)

Condición

Una condición puede ser una expresión o una declaración simple .

  • Si puede resolverse sintácticamente como una declaración de structured binding , se interpreta como una declaración de structured binding.
(since C++26)
  • Si puede resolverse sintácticamente como una expresión, se trata como una expresión. De lo contrario, se trata como una declaración que no es una declaración de enlace estructurado (desde C++26) .

Cuando el control alcanza la condición, la condición producirá un valor, que se utiliza para determinar a qué etiqueta irá el control.

Expresión

Si condition es una expresión, el valor que produce es el valor de la expresión.

Declaración

Si condition es una declaración simple, el valor que produce es el valor de la variable de decisión (ver más abajo).

Declaración de enlace no estructurado

La declaración tiene las siguientes restricciones:

  • Se ajusta sintácticamente a la siguiente forma:
  • type-specifier-seq declarator = assignment-expression
(hasta C++11)
  • attribute-specifier-seq (opcional) decl-specifier-seq declarator brace-or-equal-initializer
(desde C++11)

La variable de decisión de la declaración es la variable declarada.

Declaración de enlace estructurado

La declaración tiene las siguientes restricciones:

  • La expresión en su inicializador no puede ser de tipo array.
  • La secuencia de especificadores de declaración solo puede contener especificadores de tipo y constexpr .

La variable de decisión de la declaración es la variable inventada e introducida por la declaración .

(desde C++26)

Tipo

condition solo puede producir los siguientes tipos:

  • tipos integrales
  • tipos de enumeración
  • tipos de clase

Si el valor producido es de un tipo clase, se convierte implícitamente contextualmente a un tipo integral o de enumeración.

Si el tipo (posiblemente convertido) está sujeto a integral promotions , el valor resultante se convierte al tipo promocionado.

Etiquetas

Cualquier sentencia dentro de la switch puede ser etiquetada con una o más de las siguientes etiquetas:

attr  (opcional) case expresión-constante : (1)
attr  (opcional) default: (2)
attr - (since C++11) cualquier número de atributos
constant-expression - una expresión constante convertida del tipo ajustado de la condición switch


Una case o default label está asociada con la instrucción switch más interna que la contiene.

Si se satisface cualquiera de las siguientes condiciones, el programa está mal formado:

  • Una switch statement está asociada con múltiples case labels cuyas constant-expression s tienen el mismo valor después de conversiones.
  • Una switch statement está asociada con múltiples default labels.

Transferencia de flujo de control

Cuando la condición de una sentencia switch produce un valor (posiblemente convertido):

  • Si una de las constantes de etiqueta case asociadas tiene el mismo valor, el control se transfiere a la sentencia etiquetada por la coincidencia de etiqueta case .
  • De lo contrario, si hay una etiqueta default asociada, el control se transfiere a la sentencia etiquetada por la etiqueta default .
  • De lo contrario, ninguna de las sentencias en la sentencia switch será ejecutada.

case y default las etiquetas en sí mismas no alteran el flujo de control. Para salir de una switch declaración desde el medio, consulte break declaraciones .

Los compiladores pueden emitir advertencias sobre fallthrough (alcanzar la siguiente case o default sin un break ) a menos que el atributo [[ fallthrough ]] aparezca inmediatamente antes de la etiqueta case para indicar que el fallthrough es intencional (desde C++17) .

switch (1)
{
    case 1:
        std::cout << '1'; // imprime "1",
    case 2:
        std::cout << '2'; // luego imprime "2"
}
switch (1)
{
    case 1:
        std::cout << '1'; // imprime "1"
        break;            // y sale del switch
    case 2:
        std::cout << '2';
        break;
}

switch sentencias con inicializador

Si se utiliza init-statement , la sentencia switch equivale a

{
init-statement
switch ( condition ) statement

}

Excepto que los nombres declarados por el init-statement (si init-statement es una declaración) y los nombres declarados por condition (si condition es una declaración) están en el mismo ámbito, que también es el ámbito de statement .

(desde C++17)

Notas

Debido a que la transferencia de control no está permitida para entrar al ámbito de una variable, si una declaración es encontrada dentro de la statement , debe tener ámbito en su propio statement compuesto:

switch (1)
{
    case 1:
        int x = 0; // inicialización
        std::cout << x << '\n';
        break;
    default:
        // error de compilación: salto a default:
        // entraría en el ámbito de 'x' sin inicializarlo
        std::cout << "default\n";
        break;
}
switch (1)
{
    case 1:
        {
            int x = 0;
            std::cout << x << '\n';
            break;
        } // el ámbito de 'x' termina aquí
    default:
        std::cout << "default\n"; // sin error
        break;
}

Palabras clave

switch , case , default

Ejemplo

El siguiente código muestra varios casos de uso de la sentencia switch :

#include <iostream>
int main()
{
    const int i = 2;
    switch (i)
    {
        case 1:
            std::cout << '1';
        case 2:              // la ejecución comienza en esta etiqueta case
            std::cout << '2';
        case 3:
            std::cout << '3';
            [[fallthrough]]; // atributo C++17 para silenciar la advertencia sobre fallthrough
        case 5:
            std::cout << "45";
            break;           // se termina la ejecución de las sentencias posteriores
        case 6:
            std::cout << '6';
    }
    std::cout << '\n';
    switch (i)
    {
        case 4:
            std::cout << 'a';
        default:
            std::cout << 'd'; // no hay expresiones constantes aplicables
                              // por lo tanto se ejecuta default
    }
    std::cout << '\n';
    switch (i)
    {
        case 4:
            std::cout << 'a'; // no se ejecuta nada
    }
    // cuando se utilizan enumeraciones en una sentencia switch, muchos compiladores
    // emiten advertencias si uno de los enumeradores no es manejado
    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 sintaxis de init-statement de C++17 puede ser útil cuando no hay
    // conversión implícita a tipo integral o de enumeración
    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;
    }
    // ejemplos patológicos
    // la sentencia no tiene que ser una sentencia compuesta
    switch (0)
        std::cout << "this does nothing\n";
    // las etiquetas tampoco requieren una sentencia compuesta
    switch (int n = 1)
        case 0:
        case 1:
            std::cout << n << '\n';
}

Salida:

2345
d
red
1

Informes de defectos

Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.

DR Aplicado a Comportamiento publicado Comportamiento correcto
CWG 1767 C++98 condition s de tipos que no están sujetos a
promoción integral no podían promoverse
no promover
condition s de estos tipos
CWG 2629 C++98 condition podría ser una declaración de una variable de punto flotante prohibido

Véase también

Enlaces externos

1. Desenrollado de bucles usando el Dispositivo de Duff
2. El dispositivo de Duff puede usarse para implementar corrutinas en C/C++