Проверка нулевой / пустой строки: загрузка ЦП

У меня есть эта функция, которая будет печатать 2D-текст в OpenGL

void Text2D::printText(const BMfont &font, const char *text, const PenList &pen_list);

У меня есть несколько приложений (игр), которые часто используют это, но я никогда не передавал ему пустую строку но сейчас. Большая часть string Я использовал это std::string::c_str(),

И также, у меня есть эти варианты для проверки нуля (или проверки пустой строки).

    if (text[0] == '\0') return; // # 1
if (text == '\0') return;  //   # 2
if (text == nullptr) return; // # 3

Это будет первая инструкция, которая будет выполнена после вызова функции Text2D::printText()

Все эти проверки вызывают использование процессора около 50%, за исключением # 1, Я уверен, что это так, и это очень странно для меня.

Какая разница между этими 3? я думал # 1 а также # 2 одинаковы, и я подумал # 3 преобразует nullptr в '\0'? Зачем # 2 а также # 3 стоит слишком много использования процессора? Как правильно и безопасно проверить пустоту? C-string?

0

Решение

Нет способа (1) (только проверка, а не выполнение) быть быстрее, чем (2) и (3). Логично предположить, что следование указателю заняло бы больше циклов, чем просто проверка значения адреса.

Проверьте, например, код, сгенерированный для x86.

if (text == '\0') return -1;  //   # 2

01028C6E cmp dword ptr [текст], 0
01028C72 jne printText + 29h (01028C79h)
01028C74 или eax, 0FFFFFFFFh
01028C77 jmp printText + 4Bh (01028C9Bh)

if (text == nullptr) return 0; // # 3

01028C79 cmp dword ptr [текст], 0
01028C7D jne printText + 33h (01028C83h)
01028C7F xor eax, eax
01028C81 jmp printText + 4Bh (01028C9Bh)

  if (text[0] == '\0') return 1; // # 1

01028C83 mov eax, 1
01028C88 imul eax, eax, 0
01028C8B mov ecx, dword ptr [текст] 01028C8E movsx edx, ptr байта [ecx + eax] 01028C92 тест edx, edx
01028C94 jne printText + 4Bh (01028C9Bh)
01028C96 mov eax, 1

Обратите внимание, что вы не должны разыменовывать указатель без проверки самого указателя.

3

Другие решения

Номер 1 разыменовывает указатель, номера 2 и 3 — нет. Поэтому мы ожидаем, что первое займет больше времени, если цель указателя должна быть извлечена из памяти.

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

Следует отметить, что первый идет в строку и проверяет, не является ли она пустой; вторые два нет. Поэтому, если эта проверка выполняется вокруг какого-то большого сложного фрагмента кода, вероятно, любое ускорение, которое вы видите, является результатом пропуска этого блока, когда строка пуста (не только когда указатель равен нулю), а не чем-либо, что нужно делать. с этим тестом.

Если вы хотите считать null таким же, как пустой, то вам нужны оба теста:

if (str == nullptr || str[0] == '\0') {
// String is empty
}

так как str[0] не определено, если str является нулевым

2

По вопросам рекламы [email protected]