Что такое fast string.empty() или string.size() == 0?

Недавно во время обсуждения меня попросил программист внести некоторые изменения в код. У меня было что-то вроде:

if( mystring.size() == 0)
    // do something
else
    // do something else 

Обсуждалось использование mystring.empty() для проверки, является ли строка пустой. Теперь я согласен, что можно утверждать, что string.empty() более подробный и читаемый код, но есть ли какие-либо преимущества в производительности?

Я немного поработал и нашел эти 2 ответа, относящиеся к моему вопросу:

Оба ответа подтверждают мое утверждение о том, что string.empty() является более читаемым и не дает каких-либо преимуществ по производительности, по сравнению с string.size() == 0.

Я все еще хочу быть уверенным, если есть какие-либо реализации string, которые сохраняют внутренний логический флаг для проверки, является ли строка пустой или нет?

Или существуют другие способы использования некоторых реализаций, которые аннулируют мое требование?

Ответы

Ответ 1

Стандарт определяет empty() следующим образом:

bool empty() const noexcept;
  Возвращает: size() == 0.

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

Тем не менее, empty() ясен и ясен. Вы должны предпочесть его для size() == 0 (или !size()) для удобства чтения.

Ответ 2

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

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

  • в некоторых других контейнерах (например, списки С++ 03, но не С++ 11), size() был менее эффективным, чем empty(), что привело к некоторым советам по кодированию, чтобы предпочесть empty() над size() в общем, так, чтобы, если кому-то понадобилось позже переключить контейнер (или обобщить обработку в шаблон, где тип контейнера может меняться), для сохранения эффективности изменений не требуется.

  • отражает ли более естественный способ представления теста? - не только то, о чем вы сначала думали, либо size(), потому что вы не привыкли использовать empty(), но когда вы на 100% сосредоточены на логике кода окружения, size() или empty() лучше вписаться? Например, возможно, потому, что это один из нескольких тестов size(), и вам нравится иметь согласованность, или потому, что вы реализуете известный алгоритм или формулу, которые традиционно выражаются в терминах размера: согласование может уменьшить умственный шум/усилие при проверке реализация против формулы.

В большинстве случаев вышеприведенные факторы несущественны, а проблема в обзоре кода - это пустая трата времени.

Возможная разница в производительности

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

С++ 11 имеет больше ограничений, чем С++ 03, над поведением других функций, которые влияют на выбор реализации: data() должен быть завершен NUL (используется только как c_str()), [size()] теперь является допустимым индексом и должен вернуть ссылку на символ NUL. По разным тонким причинам эти ограничения делают еще более вероятным, что empty() будет не быстрее, чем size().

В любом случае - измерьте, если вам нужно.