Является ли спецификатор функции noexcept
направленным на повышение производительности из-за потенциального отсутствия кода учета для исключений в сгенерированном объекте и поэтому должен быть добавлен к объявлениям функций и определениям, когда это возможно? Я думаю об обертках для вызываемых объектов, в первую очередь, где noexcept
может иметь какое-то значение, хотя контрольные выражения могут "раздувать" исходный код. Стоит ли?
Не улучшает ли производительность?
Ответ 1
Топ-компиляторы производят код, который уже оптимизирован так же, как код, который нельзя выполнить, а затем случай, когда возникает исключение, обрабатывается кодом вне строки, который находит механизм обработки исключений, данные о функции. Я полагаю, что есть некоторые преимущества в размере кода, чтобы опустить это, когда он, как известно, не нужен, однако.
Вероятно, есть некоторые случаи, когда спецификация nothrow позволяет определенную оптимизацию:
int main() {
int i = 0;
try {
++i;
thing_that_cannot_throw();
++i;
thing_that_can_throw();
++i;
} catch (...) {}
std::cout << i << "\n";
}
Здесь второй ++ я мог бы теоретически переупорядочиваться перед вызовом thing_that_cannot_throw
(и i
только что инициализировался до 2
). Однако на практике это другой вопрос, поскольку реализация, которая обеспечивает гарантии состояния переменных в отладчике или в стеке над вызовом функции, хотела бы, чтобы i
имел значение 1
во время этого вызова, хотя это локальная переменная, не наблюдаемая никакими стандартными средствами.
Я подозреваю, что гарантии nothrow более ценны для программиста, чем для компилятора. Если вы пишете код, который предлагает сильную гарантию исключения, тогда обычно выполняются определенные критические операции, которые вам нужно предложить, чтобы гарантировать гарантию nothrow (свопы, ходы и деструкторы являются обычными кандидатами).
Ответ 2
Теоретически говоря, noexcept
улучшит производительность. Но это может также вызвать некоторые проблемы, с другой стороны.
В большинстве случаев он не должен указываться, потому что профи слишком мало, чтобы их можно было рассматривать, и это может привести к увеличению вашего кода. Этот пост, написанный Анджей, подробно излагает причины.
Если он слишком длинный, просто возьмите эти предложения, я заключу:
- Аннотировать функции с помощью
noexcept
if- они уже были аннотированы
throw()
, - или они хорошие кандидаты (перечислены в сообщении) и никогда не бросают наверняка,
- или они являются конструкторами перемещения, присваиваниям перемещения, чья аннотация
noexcept
не может быть правильно выведена компилятором, и их экземпляры должны быть помещены в некоторый контейнер STL.
- они уже были аннотированы
- Не комментируйте функции с помощью
noexcept
, если- Вы действительно обеспокоены снижением производительности,
- или о риске вызова
std::terminate
, - или вы просто не уверены в новой функции,
- или у вас есть сомнения, следует ли вам делать свою функцию
noexcept
или нет.