Эффективно ли время компиляции "strlen()"?

Иногда необходимо сравнить длину строки с константой.
Например:

if ( line.length() > 2 )
{
    // Do something...
}

Но я стараюсь избегать использования "магических" констант в коде.
Обычно я использую такой код:

if ( line.length() > strlen("[]") )
{
    // Do something...
}

Это более читаемо, но не эффективно из-за вызова функции.
Я написал функции шаблона следующим образом:

template<size_t N>
size_t _lenof(const char (&)[N])
{
    return N - 1;
}

template<size_t N>
size_t _lenof(const wchar_t (&)[N])
{
    return N - 1;
}

// Using:
if ( line.length() > _lenof("[]") )
{
    // Do something...
}

В сборке релизов (VisualStudio 2008) он создает довольно хороший код:

cmp    dword ptr [esp+27Ch],2 
jbe    011D7FA5 

И хорошо, что компилятор не включает строку "[]" в двоичном выходе.

Является ли это конкретной оптимизацией для компилятора или это обычное поведение?

Ответ 1

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

Ответ 2

Почему бы не

sizeof "[]" - 1;

(минус один для конечного нуля. do sizeof "[]" - sizeof '\ 0', но sizeof '\ 0' часто является sizeof (int) в C, а "- 1" является отлично читаемый.)

Ответ 3

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

Я бы предпочел использовать ваши функции шаблонов, так как они гарантированно не вызывают strlen во время выполнения. Конечно, вместо того, чтобы писать отдельные функции для char и wchar_t, вы можете добавить еще один аргумент шаблона и получить функцию, которая работает для любого типа:

template <typename Char_t, int len>
int static_strlen(const Char_t (&)[N] array){
  return len / sizeof(Char_t) - 1;
}

(Как уже упоминалось в комментариях, это даст смешные результаты, если передать массив из int, но вы, вероятно, это сделаете? Это означало для строк, в конце концов)

Наконец, имя _strlen плохое. Все имена в области пространства имен, начинающиеся с символа подчеркивания, зарезервированы для реализации. Вы рискуете некоторыми неприятными конфликтами именования.

Кстати, почему "[]" меньше магической константы, чем 2?

В обоих случаях это литерал, который нужно изменить, если формат строки, который он сравнивает с изменениями.

Ответ 4

#define TWO 2
#define STRING_LENGTH 2
/* ... etc ... */

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