Верно ли, что goto
перескакивает по битам кода без вызова деструкторов и прочего?
например
void f() {
int x = 0;
goto lol;
}
int main() {
f();
lol:
return 0;
}
Не x
будет утечки?
Верно ли, что goto
перескакивает по битам кода без вызова деструкторов и прочего?
например
void f() {
int x = 0;
goto lol;
}
int main() {
f();
lol:
return 0;
}
Не x
будет утечки?
"Won't x be leaked"
значит? Тип x
- это встроенный тип данных. Почему бы тебе не выбрать лучший пример?
goto
, они думают, что даже автоматические переменные продолжительности хранения каким-то образом «просочились». То, что мы с вами знаем иное, совершенно не относится к делу.
int
не может течь, это может быть утечка . Например: void f(void) { new int(5); }
утечка int
.
Ответы:
Предупреждение: Этот ответ относится к C ++ только ; в C.
Не
x
будет утечки?
Нет, абсолютно нет.
Это миф, что goto
некоторая низкоуровневая конструкция позволяет вам переопределить встроенные в C ++ механизмы определения области видимости. (Во всяком случае, это longjmp
может быть подвержено этому.)
Рассмотрим следующий механизм, который не позволит вам делать «плохие вещи» с ярлыками (включая case
ярлыки).
Вы не можете перепрыгивать через функции:
void f() {
int x = 0;
goto lol;
}
int main() {
f();
lol:
return 0;
}
// error: label 'lol' used but not defined
[n3290: 6.1/1]:
[..] Объем метки - это функция, в которой она появляется. [..]
Вы не можете перепрыгнуть через инициализацию объекта:
int main() {
goto lol;
int x = 0;
lol:
return 0;
}
// error: jump to label ‘lol’
// error: from here
// error: crosses initialization of ‘int x’
Если вы вернетесь назад через инициализацию объекта, то предыдущий «экземпляр» объекта будет уничтожен :
struct T {
T() { cout << "*T"; }
~T() { cout << "~T"; }
};
int main() {
int x = 0;
lol:
T t;
if (x++ < 5)
goto lol;
}
// Output: *T~T*T~T*T~T*T~T*T~T*T~T
[n3290: 6.6/2]:
[..] Передача из цикла, из блока или обратно через инициализированную переменную с автоматической продолжительностью хранения включает в себя уничтожение объектов с автоматической продолжительностью хранения, которые находятся в области видимости в точке передачи, но не в точке, переданной в . [..]
Вы не можете перейти в область видимости объекта, даже если он не инициализирован явно:
int main() {
goto lol;
{
std::string x;
lol:
x = "";
}
}
// error: jump to label ‘lol’
// error: from here
// error: crosses initialization of ‘std::string x’
... за исключением определенных типов объектов , которые язык может обрабатывать независимо от того, что они не требуют "сложной" конструкции:
int main() {
goto lol;
{
int x;
lol:
x = 0;
}
}
// OK
[n3290: 6.7/3]:
Можно передать в блок, но не в обход объявлений с инициализацией. Программа, которая перескакивает из точки, где переменная с автоматической продолжительностью хранения не находится в области видимости, к точке, где она находится в области видимости, плохо сформирована, если только переменная не имеет скалярный тип, тип класса с тривиальным конструктором по умолчанию и тривиальный деструктор, a Версия одного из этих типов с квалификацией cv или массив одного из предыдущих типов объявляется без инициализатора. [..]
Кроме того, объекты с автоматической продолжительностью хранения являются не «утечкой» , когда вы goto
из их сфер :
struct T {
T() { cout << "*T"; }
~T() { cout << "~T"; }
};
int main() {
{
T t;
goto lol;
}
lol:
return 0;
}
// *T~T
[n3290: 6.6/2]:
При выходе из области видимости (независимо от ее выполнения) объекты с автоматической продолжительностью хранения (3.7.3), которые были созданы в этой области, уничтожаются в порядке, обратном их построению. [..]
Вышеупомянутые механизмы гарантируют, что goto
вы не сломаете язык.
Конечно, это не означает автоматически , что вы «должны» использовать goto
для любой данной проблемы, но это действительно означает , что это не так «зла» , как общий миф заставляет людей верить.