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

Does throw() (то есть __declspec (nothrow)) дает реальные преимущества в Visual С++?

Сосредоточив внимание на Visual С++, вы когда-либо испытывали значительную прирост производительности в С++-кодексе, используя спецификацию throw() (т.е. __declspec(nothrow))? Помогает ли это оптимизатору? Существуют ли какие-либо тесты, показывающие прирост производительности?

Я нашел разные (противоположные) советы в Интернете:

Обоснование обоснования исключений - против throw(), вместо этого Ларри Остерман, похоже, поддерживает это в своем блоге: Зачем добавлять методы throw() к вашим методам?

(Я хотел бы уточнить, что меня интересует специфический код VС++; я знаю, что в GCC спецификация throw() может фактически быть "пессимизацией" из-за проверки времени выполнения.)

P.S. Чтение заголовков ATL, я обнаружил, что throw() используется повсеместно; Более того, я нашел удобный класс С++ RAII unique_handle в этой статье MSDN, в которой также используется спецификация throw().

4b9b3361

Ответ 1

Компилятор MSVC рассматривает его как подсказку оптимизации, да.

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

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

Ответ 2

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

class X
{
    public:
        void swap(X& rhs) throw(); // Swap better not ever throw
                                    // If it does there is something else
                                    // much more seriously wrong
};

Ответ 3

Основная проблема с throw() заключается в том, что код внутри функции, помеченный как throw(), может вызывать. Например, это будет отлично работать:

void foo() throw()
{
    throw "haha\n";
}

int main()
{
    try {
        foo();
    }
    catch(const char* s) {
        std::cout << s;
    }
    return 0;
}

Обратите внимание, что foo не будет throw до main, причины. И вы не поймаете исключение (как если бы вы прокомментировали спецификатор throw()). Вместо этого компилятор будет обертывать функцию кода блоком try{}catch(). Когда генерируется исключение, он будет обрабатываться глобальным обработчиком (это будет означать, что ваша программа по умолчанию по умолчанию).

Обратите внимание, что компилятор должен обернуть функциональный код блоком try{}cath(), если только компилятор не уверен, что внутренний код не имеет возможности генерировать исключение.

В результате может быть выполнена некоторая оптимизация с вызывающим абонентом foo, но вещи становятся более сложными внутри foo.

EDIT:

Вещи с __declspec(nothrow) отличаются: Microsft сообщает,

Этот атрибут сообщает компилятору, что объявленная функция и функции, которые он вызывает, никогда не генерируют исключение.

Это означает, что компилятор может опустить try{}catch() код оболочки.

EDIT2 На самом деле Microsoft нарушает стандартное поведение и не генерирует warpper для throw(). Ну, тогда вы можете использовать throw() для повышения производительности.