У меня есть эта функция, которая будет печатать 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
?
Нет способа (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
Обратите внимание, что вы не должны разыменовывать указатель без проверки самого указателя.
Номер 1 разыменовывает указатель, номера 2 и 3 — нет. Поэтому мы ожидаем, что первое займет больше времени, если цель указателя должна быть извлечена из памяти.
В общем, инструменты очень плохо рассказывают вам, что происходит в таких микробенчмарках.
Следует отметить, что первый идет в строку и проверяет, не является ли она пустой; вторые два нет. Поэтому, если эта проверка выполняется вокруг какого-то большого сложного фрагмента кода, вероятно, любое ускорение, которое вы видите, является результатом пропуска этого блока, когда строка пуста (не только когда указатель равен нулю), а не чем-либо, что нужно делать. с этим тестом.
Если вы хотите считать null таким же, как пустой, то вам нужны оба теста:
if (str == nullptr || str[0] == '\0') {
// String is empty
}
так как str[0]
не определено, если str
является нулевым