LG>while(1)
LG>{
LG> for(int i = 0; i < 100; i++)
LG> {
LG> if(i == 77)
LG> // вот тут хочу выйти вообще из всех циклов - из for и из while
LG> }
LG>}
LG>
LG>Как это сделать?
Использовать goto. Ничего страшного не будет при умеренном использовании goto.
LG>while(1)
LG>{
LG> for(int i = 0; i < 100; i++)
LG> {
LG> if(i == 77)
LG> // вот тут хочу выйти вообще из всех циклов - из for и из while
LG> }
LG>}
LG>
Не надо так делать. Если такой код будет находиться в деструкторе, то при раскрутке стека в строке throw 77; программа будет заверешена и никакой catch (int e) не поможет.
Здравствуйте Mishka<T>, Вы писали:
MT>Не надо так делать. Если такой код будет находиться в деструкторе, то при раскрутке стека в строке throw 77; программа будет заверешена и никакой catch (int e) не поможет.
я вот как раз и не хочу через исключения. И не хочу гоу-ту.
Чего делать?
Здравствуйте Mishka<T>, Вы писали:
MT>Здравствуйте LeonGorbachev, Вы писали:
LG>>я вот как раз и не хочу через исключения. И не хочу гоу-ту. LG>>Чего делать?
MT>Можно так: MT>
MT>while(1)
MT>{
MT> for(int i = 0; i < 100; i++)
MT> {
MT> if(i == 77)
MT> break;
MT> }
MT> if (i < 100) break;
MT>}
MT>
Это прокатит только на VC6
Я обычно делаю так:
bool bContinue = true;
while(bContinue) {
for(int i = 0; i < 100; i++) {
if (i == 77) {
bContinue = false;
break;
}
}
}
MT>Не надо так делать. Если такой код будет находиться в деструкторе, то при раскрутке стека в строке throw 77; программа будет заверешена и никакой catch (int e) не поможет.
Не пугай так народ, от и так уже запуганный.
terminate вызывается, только если второй exception не был перехвачен внутри деструктора, чего не наблюдается в данном примере.
Так что выход из вложенного цикла через исключение — нормальная ситуация.
MT>Не надо так делать. Если такой код будет находиться в деструкторе, то при раскрутке стека в строке throw 77; программа будет заверешена и никакой catch (int e) не поможет.
То что не надо так делать — это ты прав.
А на счет того, что программа будет завершена — не совсем.
Исключение ведь перехватывется, и из деструктора не выпускаться не будет, потому всё будет работать.
А делать так не надо, потому что исключение это дорогое средство и должны
происходить редко (так в книжках пишут), слно алгоритмы с их помощью реализовывать не нужно,
только обработку ошибок.
По мне так вариант с goto наиболее понятен, слно предпочтителен.
Если с души воротит от goto, то можно оформить внутренний цикл как функцию
и делать из неё return вместо goto.
Здравствуйте DarkGray, Вы писали:
DG>Здравствуйте Mishka<T>, Вы писали:
MT>>Не надо так делать. Если такой код будет находиться в деструкторе, то при раскрутке стека в строке throw 77; программа будет заверешена и никакой catch (int e) не поможет.
DG>Не пугай так народ, от и так уже запуганный.
DG>terminate вызывается, только если второй exception не был перехвачен внутри деструктора, чего не наблюдается в данном примере.
DG>Так что выход из вложенного цикла через исключение — нормальная ситуация.
А если не cекрет а почему именно ВТОРОЙ exception и в чем его отличие от первого
MT>>while(1)
MT>>{
MT>> for(int i = 0; i < 100; i++)
MT>> {
MT>> if(i == 77)
MT>> break;
MT>> }
MT>> if (i < 100) break;
MT>>}
MT>>
А>Это прокатит только на VC6
Что именно? Scoping? Тогда да. А выход прокатит везде.
2 Mishka<T>
Только это неправильное условие. Надо выйти из циклов при i == 77, а if — совсем другое условие дает (расширяет диапазон значений немеряно).
Здравствуйте Kaa, Вы писали:
Kaa>Здравствуйте Андрей, Вы писали:
А>>Это прокатит только на VC6 Kaa>Что именно? Scoping? Тогда да. А выход прокатит везде.
Что такое Scoping?
Здравствуйте Рек, Вы писали:
Рек>А делать так не надо, потому что исключение это дорогое средство и должны Рек>происходить редко (так в книжках пишут), слно алгоритмы с их помощью реализовывать не нужно, Рек>только обработку ошибок.
Есть еще способ с использованием __leave у Microsoft, и им некоторые писатели книжек пользуются, но тогда SEH надо привлекать, что часто невозможно/трудно.
Рек>Если с души воротит от goto, то можно оформить внутренний цикл как функцию Рек>и делать из неё return вместо goto.
Стоит добавить, что для встроенной функции никакого оверхеда не будет (если она компилятору понравится, конечно), а способ самый красивый. Но с добавочной переменной типа bool — еще красивее. Не так наглядна декомпозиция алгоритма, но зато потерь в производительности не будет.
Здравствуйте LeonGorbachev, Вы писали:
LG>Здравствуйте Kaa, Вы писали:
Kaa>>Здравствуйте Андрей, Вы писали:
А>>>Это прокатит только на VC6 Kaa>>Что именно? Scoping? Тогда да. А выход прокатит везде. LG>Что такое Scoping?
Я имел ввиду, что область видимости переменной, объявленной в заголовке цикла, ограничена самим циклом (так написано в стандарте). В VC6 же это не так. Областью видимости переменных, там объявленых, является объемлющая для цикла область видимости.
LG>while(1)
LG>{
LG> for(int i = 0; i < 100; i++)
LG> {
LG> if(i == 77)
LG> // вот тут хочу выйти вообще из всех циклов - из for и из while
LG> }
LG>}
LG>
LG>Как это сделать?
goto это единственный сто процентный выход из ситуации. Но выход это плохой. Лучше переделать условие циклов так, чтобы они учитывали такую ситуацию. Например:
bool b = true;
while(1)
{
for(int i = 0; b && i < 100; i++)
{
if(i == 77)
{
// вот тут хочу выйти вообще из всех циклов - из for и из
b = false;
break;
}
// Если далее есть кол...
// то дописываем проверку:if(b)
break;
// некоторый код
}
}
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте slonnik, Вы писали:
S>А если не cекрет а почему именно ВТОРОЙ exception и в чем его отличие от первого
Потому что третьего уже не будет , программа завершится раньше.
При возникновении второго не обработанного исключения у компилятора возникает дилема, какое из исключений тянуть "на верх".
Рассмотрим, пример:
//есть класс A, деструктор которого кидает исключение Exception2;struct A
{
~A() {throw Exception2();}
};
//есть сервер, который кидает исключениеvoid Server()
{
A a;
throw Exception1();
}
//и есть клиент, который их ловитvoid Client()
{
try
{
Server();
}
catch (...)
{
}
}
Так вот, если при размотке стека при обработке исключения Exception1, окажется, что сгенерировалось еще одно исключение Exception2, которое ловится "выше", чем генериется первое, то у компилятора возникает дилема, какое исключение из этих двух передать в catch. В C++ пошли наиболее простым путем, и грохают всю программу(что очень сильно мешает написанию устойчивых программ), в остальных языках(Java, C#) второе исключение просто игнорируется.
Рассматривать программу, как дерево, и проведем линии от возникновений исключений до их обработки. Если линии сливаются, то в этом случае программа будет завершена.
[skipped]
DG>Так вот, если при размотке стека при обработке исключения Exception1, окажется, что сгенерировалось еще одно исключение Exception2, которое ловится "выше", чем генериется первое, то у компилятора возникает дилема, какое исключение из этих двух передать в catch. В C++ пошли наиболее простым путем, и грохают всю программу(что очень сильно мешает написанию устойчивых программ), в остальных языках(Java, C#) второе исключение просто игнорируется.
По указанному простому пути идут программы, которые в деструкторах выбрасывают исключения и при этом не вызывают функцию
bool std::uncaught_exception();
// #import <windows.bas> class IWindows9x:protected DOS { private: virtual HANDLE EnumClouds()=0; };
Здравствуйте KA, Вы писали:
KA>По указанному простому пути идут программы, которые в деструкторах выбрасывают исключения и при этом не вызывают функцию KA>
bool std::uncaught_exception();
Так обычно выброс исключения происходит не прямо в деструкторе, а в функции, которая вызывается из деструктора. Сама функция может и не предполагать, что ее будут вызывать из деструктора.
В С++ нельзя, например, защититься от обращения по нулевому указателю внутри деструктора, что очень мешает жить программе — 24x7x365.
Предлагаешь завернуть каждый деструктор в такой код. ИМХО, это уже издевательство над программистом, лучше было бы предложить выбрать, какую модель я хочу.