#cpp #cpp11 #cpp14 #cpp17
Когда-то давно в С++ была возможность указать для метода/функции спецификацию nothrow. Которая указывала, что метод/функция не выбрасывает исключений. Как дисциплинированный пользователь, я попробовал я в свое время использовать эту спецификацию. Но вскоре выяснилось, что при разработке очень утомительно отслеживать, какие функции выбрасывают исключение, а какие нет. И я перестал указывать nothrow. Сейчас появился проект, в котором принципиально нет генерации исключений. В связи с этим появились вопросы. Вопросы: Поддерживается ли сейчас в стандарте спецификация nothrow? Рекомендована ли сейчас в стандарте спецификация nothrow? Или, как часто бывает с С++ с нововведениями, она объявлена устаревшей. Что дает использование спецификации nothrow? Может ли транслятор генерировать более быстрый/компактный код при использовании спецификации nothrow? Или никакой разницы нет? Можно ли сразу указать транслятору, что все методы класса имеют спецификацию nothrow? Чтобы не возиться с каждым методом и не указывать в нем nothrow.
Ответы
Ответ 1
Вероятно, что Вы говорит о throw(), т.к. std::nothrow это немного другое. Спецификация throw() помечена как устаревшая (deprecated) в C++17 и будет удалена из будущих стандартов, поэтому использовать её не рекомендуется. В современном стандарте есть другой спецификатор: noexcept, суть которого в том, чтобы вызывать std::terminate если исключение покидает функцию, помеченную этим спецификатором. С использованием noexcept код может получиться лучше, но основная задача этого спецификатора задавать соответствующие интерфейсы. Поэтому нет никаких механизмов, которые делают всё noexcept — каждый интерфейс должен быть явно помечен (за исключением деструкторов, которые являются noexcept по умолчанию).Ответ 2
Немного о константе std::nothrow_t nothrow и спецификаторе noexcept Известно что: Когда operator new не может выделить память, генерирует исключение std::bad_alloc. Для демонстрации напишем функцию: template < class T > void capture1(T** p) throw(std::bad_alloc) { int i{}; while (true) { try { *p++ = new T[100000]; // когда нибудь в память будет исчерпана ++i; } catch (std::bad_alloc& exc) { std::cout << "На шаге " << i << " генерирован " << exc.what() << std::endl; return; } } } Но может быть нам понадобится написать такую же функцию, не генерирующую исключение. И часто, для пользователей удобно знать, что эта функция не генерирует никакого исключения (мы об этом явно можем сказать в обьявлении функции). template < class T > void capture2(T** p) noexcept { int i{}; while (true) { // Если оператор не найдет память, то указатель просто станет нулевым *p++ = new(std::nothrow) T[100000]; // когда нибудь в память будет исчерпана ++i; if (*p == 0) { std::cout << "Память исчерпана на шаге " << i << std::endl ; return; } } } И в нашей программе: //... int** pi = new int*[100000]; capture1(pi); // на шаге i сгенерировано исключение std::bad_alloc capture2(pi); // память исчерпанa на шаге i // дальше освобождения памяти и все другое Это всего лишь демонстрация того, что и как...
Комментариев нет:
Отправить комментарий