- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
void funcMir()
{
...
if ( __mir0>5 )
goto vihod;
TMir1 __mir1; // Конструктор не вызывается. (Оператор goto перескакивает через него.)
...
vihod:
...
// Здесь вызывается деструктор для __mir1 при выходе __mir1 из области видимости.
};
неужели кто-то думает, что в плюсовых компайлерах
остался бы такой баг и был "случайно" каким-то нубом?
jump to label ‘vihod’ from here crosses initialization of ‘TMir1 __mir1’
Так что это не говнокод, а ошибочный код.
Вопрос для начала: как без goto делать break из вложенниго цикла?
Есть три вложенных цикла. В зависимости от обстоятельств надо делать выход из среднего или внешнего. Как?
Это если уж решительно идти без goto.
while(...) {
...
while(...) {
...
while(...) {
...
if(...)
goto endmiddle;
else
goto endouter;
...
}
...
}
endmiddle:
...
}
endouter:
Если goto на помойку, то как это переписать без значительного усложнения?
очень просто - вообще не писать такое
три вложенных цикла - говнокод по определению
зы. я - другой guest, если что
{
while( ... )
{
while( ... )
{
if( ... )
return END_MIDDLE;
else
return END_OUTER;
}
}
return END;
}
...
while(...)
{
int Res = Func( ... );
if( Res == END_OUTER )
break;
}
...
Вроде бы усложениния не такие значительные. Мм?
goto часто сильно усложняет процесс разбора и поддержку кода.
всегда можно написать без него. приведите, плиз, реальный пример, когда goto необходим, ибо три вложенных цикла с неясными условиями завершения - шибко надумано, да и в них можно без него.
хотя он более Си-ориентированный
void func( /*тут гдет 10 аргументов, поинтеры на различные структуры*/)
{
some_type val = init_by_arg1(arg1);
if(val)
{
cleanup(arg1);
}
//....... и так со всеми
some_action_with_some_val( val_9 );
// и потом очитка
}
надеюсь понятно проблему?
в плюсах бы решалось написанием классов с детрукторами, но тоже не всегда удобно, если нужные функции портируются из Сишных либ
а это и есть раздел про плюсы
> но тоже не всегда удобно, если нужные функции портируются из Сишных либ
а в чем проблема?
приведенный код - не более, чем плохое проектирование, как мне отсюда кажется
Мне кажется, что goto - незаменим в некоторых случаях. Все другие методы в ЭТИХ случаях только ухудшают читабильность и уменьшают скорость исполнения программы.
bool func()
{
...
if (ошибка)
{
//делаем ряд действий
return false;
}
//и этот блок встречается еще не раз
}
ИМХО лучше поставить в конце функции метку и переходить туда в случае ошибки
а если без них то берем переменную int stage = 0; после каждого шага наращиваем, если произошла ошибка, то загоняем эту переменную в switch и выполняем действия обратные сделанным.
пример
int stage = 0;
ptr1 = new Obj1();
error = ptr1 == NULL;
if (!error)
{
stage++;
ptr2 = new Obj2();
error = ptr2 == NULL;
if (!error)
{
stage ++;
.............
}
}
.....
if (error)
{
switch(stage)
{
case 2:
delete ptr2;
case 1:
delete ptr1;
}
}
то есть goto я бы не использовал ни при каких обстоятельствах, и еще ниразу не встречал код который нельзя переписать без goto
Никто не встречал и не встретит.
Идея структурного программирования как раз и основана на том, что любой алгоритм можно закодировать в виде комбинации последовательного выполнения, ветвления и цикла. Это давно доказано, и не надо изобретать вечный двигатель. Но вопрос в другом: действительно ли оправдан отказ от goto.
если бы от него отказались, то не было бы такого keyword'a :)
пользуйтесь наздоровье и надейтесь, что это не выйдет боком впоследствии.
к счастью, в промышленном коде - goto редкостная редкость.
зато в говноопенсорсе часто вижу :( в общем, как и хреновое форматирование и имена переменных вида s, ss, a, b и иже с ними.
В джаве нет оператора goto, но есть ключевое слово goto
Видимо, создатели сами не были уверены в успехе отказа :)
а в проприетарщине и не увидишь
есть мнение, что именно гоу ту и делают циклы
случайно не так:
try
{
if(!val)
{
// ...............
throw 1;
}
/// do some
if(!val2)
{
// ...............
throw 2;
}
//.............
}
catch
{
//some cleanup
}
(:
еще ужаснее, чем предыдущий пример.
и медленнее.
вообще это неправильное использование exceptions :)
для обработки ошибок и их последствий есть авто-птр, деструкторы, эксепшны, функции, но гото практически всегда наводит на мысль о кривости кода :)
Конечно, лучше максимально избегать использования goto - рефакторить код и т.д.
Иногда приходится его использовать в очень сложных случаях (опять же, например, когда используются макросы va_start и т.д. Функции не вызовешь, а то стек попортится...)
Короче, кто за гото - тот долбоёб, кто против гото - тот тоже долбоёб.