Выражения if
и switch
с инициализаторами по сути являются синтаксическим сахаром. Два следующих фрагмента кода эквивалентны:
{
auto var (init_value); if (condition) {
// Ветвь A. К переменной var можно получить доступ
} else {
// Ветвь B. К переменной var можно получить доступ
}
// К переменной var все еще можно получить доступ
}
if (auto var (init_value); condition) {
// Ветвь A. К переменной var можно получить доступ
} else {
// Ветвь B. К переменной var можно получить доступ
}
// К переменной var больше нельзя получить доступ
То же верно и для выражений switch
.
{
auto var (init_value); switch (var) {
case 1: ...
case 2: ...
...
}
// К переменной var все еще можно получить доступ
}
switch (auto var (init_value); var) {
case 1: ...
case 2: ...
...
}
// К переменной var больше нельзя получить доступ
Благодаря описанному механизму область видимости переменной остается минимальной. До С++17 этого можно было добиться только с помощью дополнительных фигурных скобок, как показано в соответствующих примерах. Короткие жизненные циклы уменьшают количество переменных в области видимости, что позволяет поддерживать чистоту кода и облегчает рефакторинг.
Дополнительная информация
Еще один интересный вариант — ограниченная область видимости критических секций. Рассмотрим следующий пример:
if (std::lock_guard
// Делаем что-нибудь
}
Сначала создается std::lock_guard
. Этот класс принимает мьютекс в качестве аргумента конструктора. Он
Не менее интересный пример — это область видимости слабых указателей. Рассмотрим следующий фрагмент кода:
if (auto shared_pointer (weak_pointer.lock()); shared_pointer != nullptr) {
// Да, общий объект еще существует
} else {
// К указателю shared_pointer можно получить доступ, но он является нулевым
}
// К shared_pointer больше нельзя получить доступ
Это еще один пример с бесполезной переменной shared_pointer
. Она попадает в текущую область видимости, несмотря на то что потенциально является бесполезной за пределами условного блока if
или дополнительных скобок!
Выражения if
с инициализаторами особенно хороши при работе с
if (DWORD exit_code; GetExitCodeProcess(process_handle, &exit_code)) {
std::cout << "Exit code of process was: " << exit_code << '\n';
}
// Бесполезная переменная exit_code не попадает за пределы условия if
GetExitCodeProcess
— функция API ядра Windows. Она возвращает код для заданного дескриптора процесса, но только в том случае, если данный дескриптор корректен. После того как мы покинем этот условный блок, переменная станет бесполезной, поэтому она не нужна в нашей области видимости.
Возможность инициализировать переменные внутри блоков if
, очевидно, очень полезна во многих ситуациях, особенно при работе с устаревшими API, которые используют выходные параметры.
if
и switch
. Это позволит сделать код более компактным, простым для чтения, а в случае рефакторинга его будет проще перемещать.
Новые правила инициализатора с фигурными скобками