2010-07-22 2 views
2

Мне кажется, что если у вас есть некоторые C++ код, как это:C++ Exception Throw/Поймать Оптимизации

int f() 
{ 
    try { 
    if(do_it() != success) { 
     throw do_it_failure(); 
    } 
    } catch(const std::exception &e) { 
    show_error(e.what()); 
    } 
} 

Компилятор Си ++ должен быть в состоянии оптимизировать бросок и поймать в почти простой Гото.

Тем не менее, мне кажется, что я разбираюсь в разборке и прохождении кода, что компиляторы всегда прыгать через очень грязные библиотеки обработки исключений.

Почему они это делают? Есть ли какое-то требование языка, которое предотвращает оптимизацию? Что делать, если это было:

int f() 
{ 
    try { throw std::runtime_error("Boo!"); } 
    catch (const std::exception &e) { std::cout << e.what() << std::endl; } 
} 

Почему компилятор не просто переписать, что, как

int f() 
{ 
    std::cout << "Boo!" << std::endl; 
} 
+5

Возможно, потому что в C/C++ исключения не предназначены для управления потоком, а для фактических исключений и, следовательно, рассматриваются как несколько неприкосновенные с точки зрения реализации. – Amber

+0

В последнем случае вы предполагаете, что std :: runtime_error() имеет конструктор и конструктор копирования, который не имеет побочных эффектов. Хотя это верно, компилятор может и не знать этого. –

+0

@Martin: По крайней мере, конструкция _copy_ может быть легко удалена компиляторами. Вы не должны полагаться на создаваемые конструкторы. – sbi

ответ

6

Почему они это делают?

Поскольку C++ исключения является для, ну, исключительных обстоятельств и производительность при исключительных обстоятельствах не имеют никакого значения.

Исключения из C++ были разработаны с учетом того, что поставщики компилятора могут обеспечить почти оптимальную производительность в общем случае без исключения исключений за счет снижения производительности по сравнению с возможными в нечетном случае, когда исключения бросаются.

С самого начала пользователям было рекомендовано использовать исключения только в исключительных обстоятельствах, а разработчикам было предложено оптимизировать случай отсутствия исключения (адреса деструкторов должны храниться где-то, чтобы вызвать деструкторы при возникновении исключения) на стоимость исключительного случая.
И хотя разработчики могли бы потратить ресурсы на оптимизацию нечетного исключительного случая, большинству пользователей это не понравится, так как всегда есть гораздо более важные вещи, которые нуждаются в улучшении.

5

Поскольку do_it() может бросить другое исключение, прежде чем выбросить do_it_failure();

Что касается второго примера, компилятор мог бы это сделать, но его нужно было бы рассматривать как особый случай, так зачем беспокоиться о таком патологическом случае?

+1

Функция * может * выбросить другое исключение. Но компилятор * знает *, что хотя бы один путь выполнения * делает * throw и сразу же пойман, поэтому для этого пути он может перейти непосредственно в блок catch. Если захочет. –

Смежные вопросы