Оператор switch
Передает управление одному из нескольких операторов в зависимости от значения условия.
Синтаксис
атрибут (необязательно) switch ( инициализирующий оператор (необязательно) условие ) оператор |
| атрибут | - | (с C++11) любое количество атрибутов | ||
| инициализирующий оператор | - | (с C++17) любой из следующих:
;, поэтому его часто неформально описывают как выражение или объявление, за которым следует точка с запятой. |
||
| условие | - | любой из следующих:
Значение условия должно быть целочисленного или перечислимого типа или типа класса, явный преобразование которого в целочисленный или перечислимый тип. Если тип (возможно, преобразованный) подвержен целочисленным повышениям, условие преобразуется в тип после повышения. |
||
| оператор | - | любой оператор (как правило, составной оператор). case: и default: метки разрешены в операторе, а break; оператор имеет особое значение. |
атрибут (необязательно) case константное выражение : оператор | (1) | |
атрибут (необязательно) default : оператор | (2) |
| константное выражение | - | константное выражение того же типа, что и тип условия после преобразований и целочисленных преобразований |
Объяснение
Тело оператора switch может иметь любое количество case: меток, при условии, что значения всех константных выражений уникальны (после преобразований/повышений). Максимально одна default: метка может присутствовать (хотя вложенные операторы switch могут использовать свои собственные default: метки или иметь case: метки, константы которых идентичны тем, которые используются во внешнем операторе switch).
Если условие вычисляется до значения, равного значению одного из константных выражений, то управление передается оператору, помеченному этим константным выражением.
Если условие вычисляется до значения, которое не соответствует ни одной из case: меток, и метка default: присутствует, то управление передается оператору, помеченному меткой default:.
Если условие вычисляется до значения, которое не соответствует ни одной из case: меток, и метка default: отсутствует, то ни один из операторов в теле оператора switch не выполняется.
Оператор break, встречающийся в операторе, завершает оператор switch:
switch (1)
{
case 1:
std::cout << '1'; // prints "1",
case 2:
std::cout << '2'; // then prints "2"
}switch (1)
{
case 1:
std::cout << '1'; // prints "1"
break; // and exits the switch
case 2:
std::cout << '2';
break;
}| Компиляторы могут выдавать предупреждения о продолжении (достижение следующей метки case без break), если атрибут Если инициализирующий оператор используется, оператор switch эквивалентен
За исключением того, что имена, объявленные инициализирующим оператором (если инициализирующий оператор является объявлением) и имена, объявленные условием (если условие является объявлением), находятся в одном пространстве имен, которое также является пространством имен оператора. | (с C++17) |
Поскольку передача управления не разрешена для входа в область видимости переменной, если встречается оператор объявления внутри оператора, он должен быть ограничен своим собственным составным оператором:
switch (1)
{
case 1:
int x = 0; // initialization
std::cout << x << '\n';
break;
default:
// compilation error: jump to default:
// would enter the scope of 'x' without initializing it
std::cout << "default\n";
break;
}switch (1)
{
case 1:
{
int x = 0;
std::cout << x << '\n';
break;
} // scope of 'x' ends here
default:
std::cout << "default\n"; // no error
break;
}Ключевые слова
Пример
Следующий код демонстрирует несколько вариантов использования оператора switch
#include <iostream>
int main()
{
const int i = 2;
switch (i)
{
case 1:
std::cout << '1';
case 2: // execution starts at this case label
std::cout << '2';
case 3:
std::cout << '3';
[[fallthrough]]; // C++17 attribute to silent the warning on fallthrough
case 5:
std::cout << "45";
break; // execution of subsequent statements is terminated
case 6:
std::cout << '6';
}
std::cout << '\n';
switch (i)
{
case 4:
std::cout << 'a';
default:
std::cout << 'd'; // there are no applicable constant expressions
// therefore default is executed
}
std::cout << '\n';
switch (i)
{
case 4:
std::cout << 'a'; // nothing is executed
}
// when enumerations are used in a switch statement, many compilers
// issue warnings if one of the enumerators is not handled
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;
}
// the C++17 init-statement syntax can be helpful when there is
// no implicit conversion to integral or enumeration type
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;
}
// pathological examples
// the statement doesn't have to be a compound statement
switch (0)
std::cout << "this does nothing\n";
// labels don't require a compound statement either
switch (int n = 1)
{
case 0:
case 1:
std::cout << n << '\n';
}
}Вывод:
2345 d red 1
Отчеты об ошибках
Следующие отчеты об ошибках, изменяющие поведение, были применены ретроактивно к ранее опубликованным стандартам C++.
| DR | Применимо к | Поведение при публикации | Правильное поведение |
|---|---|---|---|
| CWG 1767 | C++98 |
условия типов, которые не подлежат целочисленному повышению, не могли быть повышены | не повышать условия этих типов |
| CWG 2629 | C++98 | условие могло быть объявлением переменной с плавающей точкой | запрещено |
См. также
C документация для switch |
Внешние ссылки
| 1. | Развертывание циклов с помощью устройства Даффа |
| 2. | Устройство Даффа может использоваться для реализации сопроцедур в C/C++ |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/language/switch