Какие алгоритмы и контейнеры в С++ 11 STL могут идти быстрее, если тип не является исключением?
На работу пришли дискуссии о том, как много заботиться об использовании noexcept. Мы все знаем, что noexcept на самом деле не делает огромную сумму для оптимизатора компилятора, за исключением внешне определенного кода, который компилятор в противном случае может предположить, может бросить, потому что он не может знать его реализацию, поэтому единственное реальное преимущество в производительности для маркировки вещей noexcept для кода, который использует std:: move_if_noexcept < > , который будет предполагаться, будет главным образом контейнерами STL и их алгоритмами.
Таким образом, оценка будет такой: do не использовать noexcept, если:
-
extern-функции и классы, где реализация вызываемого не известна компилятору.
-
Переместите конструкторы, переместите операторы присваивания и замените их на любой тип, который может содержаться в контейнере STL.
-
В противном случае не беспокойтесь об этом.
Является ли это справедливой оценкой? Существуют ли другие места в STL, которые генерируют гораздо более оптимальный код, если что-то не так? Если да, то какая реализация STL - это то, что нужно отметить, за исключением того, что она работает, и какие результаты эффективности производительности (меньшее количество распределений памяти, более низкая сложность)?
Изменить: Made CashCow предложил изменить формулировку.
Ответы
Ответ 1
Является ли это справедливой оценкой?
Нет... он излишне хрупкий во время разработки/обслуживания кода. Посмотрите, что произойдет, если вы будете следовать своим правилам для этого кода...
// awesome_lib.h
void f() noexcept; // out-of-line implementation: { }
// awesome_app.cpp
void c1() noexcept; // out-of-line implementation: { f(); }
// cool_app.cpp
void c2() noexcept; // out-of-line implementation: { f(); }
... скажем, f()
хочет сообщить новый класс проблемы через исключения, поэтому он удаляет noexcept
и условно выбрасывает... если весь код клиента, вызывающий f()
- c1
, c2
,... найден и обновлен, приложения могут std::terminate
вместо того, чтобы исключение распространялось на любое предложение catch
, в противном случае могло бы быть доступно. Зачем вам это нужно? Да, вы могли бы использовать оператор noexcept
, чтобы выразить несуществующий характер c1
и c2
в терминах f
и других вызываемых функций, но этот многословный и хрупкий. Это не похоже на const
, где ошибки компилятора помогают вам поддерживать согласованность.
Лучше использовать целевое использование noexcept
там, где это требуется для конкретной оптимизации оптимизации.