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

Какие алгоритмы и контейнеры в С++ 11 STL могут идти быстрее, если тип не является исключением?

На работу пришли дискуссии о том, как много заботиться об использовании noexcept. Мы все знаем, что noexcept на самом деле не делает огромную сумму для оптимизатора компилятора, за исключением внешне определенного кода, который компилятор в противном случае может предположить, может бросить, потому что он не может знать его реализацию, поэтому единственное реальное преимущество в производительности для маркировки вещей noexcept для кода, который использует std:: move_if_noexcept < > , который будет предполагаться, будет главным образом контейнерами STL и их алгоритмами.

Таким образом, оценка будет такой: do не использовать noexcept, если:

  • extern-функции и классы, где реализация вызываемого не известна компилятору.

  • Переместите конструкторы, переместите операторы присваивания и замените их на любой тип, который может содержаться в контейнере STL.

  • В противном случае не беспокойтесь об этом.

Является ли это справедливой оценкой? Существуют ли другие места в STL, которые генерируют гораздо более оптимальный код, если что-то не так? Если да, то какая реализация STL - это то, что нужно отметить, за исключением того, что она работает, и какие результаты эффективности производительности (меньшее количество распределений памяти, более низкая сложность)?

Изменить: Made CashCow предложил изменить формулировку.

4b9b3361

Ответ 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 там, где это требуется для конкретной оптимизации оптимизации.