Есть ли разница между спецификацией noexcept и empty throw для лямбда-выражения?

Учитывая пример:

double values[] {2.5, -3.5, 4.5, -5.5, 6.5, -7.5};
std::vector<double> squares(std::end(values) - std::begin(values));

std::transform(std::begin(values), std::end(values), std::begin(values), std::begin(squares),
    [](double x1, double x2) throw() { return x1 * x2; });
  1. Является ли это функционально эквивалентным следующему?

    [](double x1, double x2) noexcept { return x1 * x2; })
    
  2. Есть ли убедительная причина, почему я должен помечать такое выражение (или подобные базовые выражения) либо модификаторами, либо в этом случае лучше оставить его и просто не заморачиваться?


person Grzegorz Szpetkowski    schedule 25.05.2016    source источник


Ответы (2)


Есть ли разница между спецификацией noexcept и empty throw...?

Да, есть.

Первое различие, которое приходит на ум, — что произойдет, если будет выброшено исключение?

  • В случае throw() вызывается std::unexpected(). Обработчик по умолчанию для unexpected вызовет terminate.
  • В случае noexcept вызывается std::terminate().

Во-вторых, спецификация динамического исключения устарела.

Устарело

noexcept — это улучшенная версия throw(), которая устарела в C++11. В отличие от throw(), noexcept не будет вызывать std::unexpected и может раскручивать стек, а может и нет, что потенциально позволяет компилятору реализовать noexcept без накладных расходов времени выполнения throw().


Есть ли убедительная причина, по которой я должен помечать такое выражение (или аналогичные базовые выражения) каким-либо модификатором...?

Это выражение намерения. Если вы хотите, чтобы лямбда никогда не выбрасывала, и если это происходит, это считается фатальным для выполнения программы, тогда да, вы должны пометить лямбду как noexcept (throw() устарело).

person Niall    schedule 25.05.2016

Да, их обоих можно использовать для объявления функций (включая лямбда-выражения), которые не генерируют никаких исключений, но динамическая спецификация исключений объявлена ​​устаревшей в C++11. И noexcept (то же самое, что noexcept(true)) и throw() не совсем одно и то же:

noexcept — это улучшенная версия throw(), которая устарела в C++11. В отличие от throw(), noexcept не будет вызывать std::unexpected и может или не может раскрутить стек, что потенциально позволяет компилятору реализовать noexcept без накладных расходов времени выполнения throw().

person songyuanyao    schedule 25.05.2016