Я думаю, что принятый ответ является довольно неинформативным, если не неправильным, поэтому даже после стольких лет я чувствую необходимость предложить правильный ответ.
Рассуждать о том, почему разработчики компиляторов решили не прилагать усилий к какой-либо конкретной функции, - это просто ... предположение. Тот факт, что исключения генерируются только в исключительных обстоятельствах, обычно не рассматривается как причина не оптимизировать производительность такого кода. Напротив, даже если верно, что генерирующий код не оптимизирован за счет не-генерирующего кода, инфраструктура создания и обработки исключений, тем не менее, оптимизируется очень тщательно.
Кроме того, этот фрагмент кода может казаться настолько изобретательным, что не стоит обдумывать, но это не так: он может быть результатом встраивания и оптимизации гораздо более сложного кода, а его оптимизация может привести к более простому коду, который позволяет выполнять другую оптимизацию переходит в огонь, или содержащая функция для дальнейшего встраивания. Подобные этапы оптимизации, когда они правильные и эффективные для реализации, всегда заслуживают, по крайней мере, рассмотрения, независимо от того, насколько вычурным может выглядеть оригинальный фрагмент кода. В противном случае можно избежать даже фундаментальных проходов, таких как устранение мертвого кода , потому что "мертвый код не должен быть написан в первую очередь". Что, очевидно, не так.
Следовательно, я просто не согласен с принятым ответом. Тот факт, что исключения должны создаваться исключительно, является , а не причиной, по которой этот код не оптимизирован.
Причина носит чисто технический характер и объясняется в этом электронном письме из списка рассылки clang development: http://lists.llvm.org/pipermail/cfe-dev/2015-March/042035.html
Подводя итог, язык позволяет коду, вызываемому внутри блока catch
, перебрасывать исключение в любой точке, "даже не видя" объект исключения:
void g() { throw; }
Следовательно, рассмотрим код OP:
int f()
{
try { throw std::runtime_error("Boo!"); }
catch ( const std::exception &e ) { std::cout << e.what() << std::endl; }
}
Что касается компилятора, e.what()
или два вызова operator<<
могут перебросить исключение, следовательно, оптимизация кода обработки исключений нарушит семантику программы.
Чтобы этого не произошло, потребуются «знания всей программы», как написано в приведенном выше сообщении электронной почты. Даже в простых случаях можно оптимизировать , например:
int func() {
try {
throw 42;
}catch(int x) {
return x;
}
}
Код выше можно преобразовать в return 42
. Нет никаких технических причин, которые мешают этому.
Тем не менее, большинство распространенных компиляторов этого не делают ( godbolt ). На этот раз мы можем сказать из фактического источника, по электронному адресу, указанному выше, что разработчики Clang (мы не можем ничего сказать о других компиляторах) не считают эту оптимизацию оправданной, вероятно , потому что она будет применяться только catch
блоки, которые не выполняют вызовы функций.
В любом случае, в сообщении ничего не говорится о том, примут ли они патч для этого.