Подтвердить что ты не робот

Не улучшает ли производительность?

Является ли спецификатор функции noexcept направленным на повышение производительности из-за потенциального отсутствия кода учета для исключений в сгенерированном объекте и поэтому должен быть добавлен к объявлениям функций и определениям, когда это возможно? Я думаю об обертках для вызываемых объектов, в первую очередь, где noexcept может иметь какое-то значение, хотя контрольные выражения могут "раздувать" исходный код. Стоит ли?

4b9b3361

Ответ 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_throwi только что инициализировался до 2). Однако на практике это другой вопрос, поскольку реализация, которая обеспечивает гарантии состояния переменных в отладчике или в стеке над вызовом функции, хотела бы, чтобы i имел значение 1 во время этого вызова, хотя это локальная переменная, не наблюдаемая никакими стандартными средствами.

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

Ответ 2

Теоретически говоря, noexcept улучшит производительность. Но это может также вызвать некоторые проблемы, с другой стороны.

В большинстве случаев он не должен указываться, потому что профи слишком мало, чтобы их можно было рассматривать, и это может привести к увеличению вашего кода. Этот пост, написанный Анджей, подробно излагает причины.

Если он слишком длинный, просто возьмите эти предложения, я заключу:

  • Аннотировать функции с помощью noexcept if
    • они уже были аннотированы throw(),
    • или они хорошие кандидаты (перечислены в сообщении) и никогда не бросают наверняка,
    • или они являются конструкторами перемещения, присваиваниям перемещения, чья аннотация noexcept не может быть правильно выведена компилятором, и их экземпляры должны быть помещены в некоторый контейнер STL.
  • Не комментируйте функции с помощью noexcept, если
    • Вы действительно обеспокоены снижением производительности,
    • или о риске вызова std::terminate,
    • или вы просто не уверены в новой функции,
    • или у вас есть сомнения, следует ли вам делать свою функцию noexcept или нет.