Оператор 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 эквивалентен
За исключением имён, объявленных оператором инициализации (если оператор инициализации является объявлением), и имена, объявленные условием (если условие является объявлением), находятся в одной и той же области видимости, что и область видимости оператора. |
(начиная с C++17) |
Поскольку передача управления не может входить в область видимости переменной, если оператор объявления встречается внутри выражения, её область видимости должна быть определена в её собственном составном операторе:
[править] Ключевые слова
[править] Пример
В следующем коде показано несколько вариантов использования оператора switch
#include <iostream> int main() { const int i = 2; switch (i) { case 1: std::cout << '1'; case 2: // выполнение начинается с этой метки case std::cout << '2'; case 3: std::cout << '3'; [[fallthrough]]; // атрибут С++17 для отключения предупреждения о провале case 5: std::cout << "45"; break; // выполнение последующих операторов прекращается case 6: std::cout << '6'; } std::cout << '\n'; switch (i) { case 4: std::cout << 'a'; default: std::cout << 'd'; // нет применимых константных выражений, // поэтому выполняется значение по умолчанию } std::cout << '\n'; switch (i) { case 4: std::cout << 'a'; // ничего не выполняется } // когда перечисления используются в операторе switch, многие компиляторы выдают // предупреждения, если один из перечислителей не обрабатывается enum color { RED, GREEN, BLUE }; switch (RED) { case RED: std::cout << "красный\n"; break; case GREEN: std::cout << "зелёный\n"; break; case BLUE: std::cout << "синий\n"; break; } // синтаксис оператора инициализации C++17 может быть полезен, когда нет // неявного преобразования в целочисленный тип или тип перечисления 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; } // патологические примеры // оператор не обязательно должен быть составным оператором switch (0) std::cout << "это ничего не делает\n"; // метки также не требуют составного оператора switch (int n = 1) { case 0: case 1: std::cout << n << '\n'; } }
Вывод:
2345 d красный 1
[править] Отчёты о дефектах
Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:
Номер | Применён | Поведение в стандарте | Корректное поведение |
---|---|---|---|
CWG 1767 | C++98 | условия типов, которые не подлежат целочисленному продвижению, не могут быть продвинуты |
условия этих типов не продвигаются |
[править] Смотрите также
Документация C по switch
|
[править] Внешние ссылки
1. | Развертывание цикла с помощью устройства Даффа |
2. | Устройство Даффа можно использовать для реализации сопрограмм на C/C++ |