Оператор goto
Безусловно передаёт управление.
Используется, когда иначе невозможно передать управление в нужное место с помощью других операторов.
Синтаксис
атрибуты (необязательно) goto метка ;
|
|||||||||
Объяснение
Оператор goto передаёт управление в место, указанное меткой. Оператор goto должен находиться в той же функции, что и метка, на которую он ссылается, он может стоять до или после метки.
Если передача управления выходит за пределы области видимости каких-либо автоматических переменных (например, при переходе назад к точке перед объявлениями таких переменных или при переходе вперёд из составного оператора, в котором переменные ограничены областью видимости), деструкторы вызываются для всех переменных, из области видимости которых осуществляется выход, в порядке обратном порядку их построения.
Оператор goto не может передать управление в блок try или в предложение catch, но может передать управление из блока try или предложения catch (соблюдаются приведённые выше правила в отношении автоматических переменных в области видимости).
Если передача управления входит в область видимости каких-либо автоматических переменных (например, при переходе вперёд через оператор объявления), программа некорректна (не может быть скомпилирована), если только все переменные, область видимости которых является текущей, не имеют значения
(Примечание: ко всем формам передачи контроля применяются одни и те же правила)
Ключевые слова
Примечание
В языке программирования C оператор goto имеет меньше ограничений и может входить в область видимости любой переменной, кроме массива переменной длины или указателя на изменяемую переменную.
Пример
#include <iostream>
struct Object {
// нетривиальный деструктор
~Object() { std::cout << 'd'; }
};
struct Trivial {
double d1;
double d2;
}; // тривиальный конструктор и деструктор
int main()
{
int a = 10;
// цикл с использованием goto
label:
Object obj;
std::cout << a << ' ';
a -= 2;
if (a != 0) {
goto label; // выходит за область видимости obj, вызывает деструктор obj
}
std::cout << '\n';
// goto можно использовать для эффективного выхода из многоуровневых (вложенных) циклов
for (int x = 0; x < 3; ++x) {
for (int y = 0; y < 3; ++y) {
std::cout << '(' << x << ',' << y << ") " << '\n';
if (x + y >= 3) {
goto endloop;
}
}
}
endloop:
std::cout << '\n';
goto label2; // переход в область видимости n и t
[[maybe_unused]] int n; // нет инициализатора
[[maybe_unused]] Trivial t; // тривиальный конструктор/деструктор, без инициализатора
// int x = 1; // ошибка: есть инициализатор
// Object obj2; // ошибка: нетривиальный деструктор
label2:
{
Object obj3;
goto label3; // переход вперёд, за область видимости obj3
}
label3:
std::cout << '\n';
}
Вывод:
10 d8 d6 d4 d2
(0,0)
(0,1)
(0,2)
(1,0)
(1,1)
(1,2)
d
d
Смотрите также
Документация C по goto
|
Внешние ссылки
|
Популярное эссе Эдсгера В. Дейкстры, “Goto Считается Вредным” (первоначально в "Письме к сообщениям ACM (CACM)", том 11 #3, март 1968, стр. 147-148.), представляет обзор многих тонких проблем, которые может создать неосторожное использование этого ключевого слова. |