Г
Грокаем C++
@grokaemcpp9.3K подп.
2.9Kпросмотров
31.1%от подписчиков
11 марта 2026 г.
Score: 3.2K
switch #новичкам switch - это такая базовая штука, которая изучается в самом начале вместе с другими core-конструкциями языка типа условий и циклов. Правда после изучения она становится той книжкой на полке, которую редко трогают и ее достают скорее, чтобы протереть. Поэтому некоторые особенности switch забываются, а в голове новичков зачастую нет понимания, когда и как его все-таки использовать. Сегодня проясним особенности, а в следующий раз поговорим о кейсах применимости. Но для начала пойдем с начала. switch - это чуть более компактное и продвинутое условие. Скажем, у вас есть переменная типа int и в зависимости от ее значений, вы по разному обрабатываете данные. Пусть у вас есть http статус код и вы на его основе строите какую-то логику: switch(status_code) { case 200: // OK processSuccess(); break; // ... case 400: // Bad Request logClientError(status_code); break; // ... case 500: // Service Unavailable logServerError(status_code); break; // ... default: handleUnknownStatus(status_code); break; } То есть 1 переменная - много вариантов развития событий. Теперь погнали по особенностям: 👉🏿 Вы будете проваливаться в нижележащие кейсы, если не напишите break в конце текущего кейса. Это накладывает свои когнитивные сложности, но дает и возможности. Если у вас одинаково обрабатываются разные значения, то вы можете проваливаться в нижележащие кейсы, пока не дойдете до нужного обработчика и не брякнитесь(встретите break): switch(status_code) { case 200: // OK processSuccess(); break; case 400: // Bad Request case 401: // Unauthorized case 403: // Forbidden case 404: // Not Found logClientError(status_code); break; } 👉🏿 Не очень удобно в switch работать с диапазонами значений. Скорее всего выразительнее и безопаснее воспользоваться обычными условиями, если у вас обработчики соответствуют длинным диапазонам. Существуют расширения компилятора, которые позволяют указывать в switch диапазон: switch(x) { case 0 ... 9: // GNU Extension std::cout << "0-9&#092;n"; break; case 10 ... 19: // GNU Extension std::cout << "10-19&#092;n"; break; } Но это непереносимо и вообще не для этого розочка цвела. switch хорошо оптимизируется через jump table(вместо кучи if-else с линейной сложностью используется массив меток обработчиков, в котором за О(1) ищется нужный), а диапазоны значений в эту концепцию не вписываются. 👉🏿 В С++ очень органично вписаны объекты и пользовательские типы, наряду с тривиальными С-совместимыми типами. Поэтому может сложиться впечатление, что switch может, например, со строками работать. Но нет, он работает только с целочисленными типами, то есть с целыми числами и перечислениями(scoped и unscoped). Если хотите выбирать обработчики на основе пользовательских типов, нужно использовать ассоциативные контейнеры: using Handler = std::function<void()>; std::unordered_map<std::string, Handler> handlers = { {"start", &start}, {"stop", []{ stop(); }} }; void execute(const std::string& cmd) { if (auto it = handlers.find(cmd); it != handlers.end()) { it->second(); } } 👉🏿 Значения кейсов должны быть константными выражениями. То есть значениями, известными на этапе компиляции. Вы не можете выбрать обработчик, соотвествующий runtime значению. При использовании enum'ов такой проблемы в принципе не возникает, но вот с int'ами да: constexpr int getValue() { return 10; } int main() { constexpr int y = getValue(); int z = getValue(); int x = 10; switch (x) { case y: // OK: y - constant expression std::cout << "x equals y&#092;n"; break; case z: // ERROR: z is runtime value std::cout << "x equals z&#092;n"; break; default: std::cout << "default&#092;n"; } return 0; } Вроде простая конструкция, но все равно есть нюансы. Explore nuances. Stay cool.
2.9K
просмотров
4000
символов
Нет
эмодзи
Нет
медиа

Другие посты @grokaemcpp

Все посты канала →
switch #новичкам switch - это такая базовая штука, которая и — @grokaemcpp | PostSniper