Итак, я поигрался с некоторым кодом и хотел посмотреть, какой метод преобразования std :: string в верхний регистр был наиболее эффективным. Я подумал, что оба они будут примерно одинаковыми по производительности, но я был ужасно неправ. Теперь я хотел бы узнать почему.
Первый метод преобразования строки работает следующим образом: для каждого символа в строке (сохранить длину, выполнить итерацию от 0 до длины), если он находится между 'a' и 'z', сдвинуть его так, чтобы он находился между Вместо «А» и «Я».
Второй метод работает следующим образом: для каждого символа в строке (начиная с 0, продолжайте, пока мы не встретим нулевой терминатор), примените сборку в функции toupper ().
Вот код:
#include <iostream>
#include <string>
inline std::string ToUpper_Reg(std::string str)
{
for (int pos = 0, sz = str.length(); pos < sz; ++pos)
{
if (str[pos] >= 'a' && str[pos] <= 'z') { str[pos] += ('A' - 'a'); }
}
return str;
}
inline std::string ToUpper_Alt(std::string str)
{
for (int pos = 0; str[pos] != '\0'; ++pos) { str[pos] = toupper(str[pos]); }
return str;
}
int main()
{
std::string test = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~!@#$%^&*()_+=-`'{}[]\\|\";:<>,./?";
for (size_t i = 0; i < 100000000; ++i) { ToUpper_Reg(test); /* ToUpper_Alt(test); */ }
return 0;
}
Первый метод ToUpper_Reg
занял около 169 секунд на 100 миллионов итераций.
Второй метод Toupper_Alt
занял около 379 секунд на 100 миллионов итераций.
Что дает?
Редактировать: Я изменил второй метод так, что он выполняет итерацию строки, как и первый (отложите длину, цикл пока меньше длины), и это немного быстрее, но все же примерно в два раза медленнее.
Редактировать 2: Спасибо всем за ваши материалы! Данные, которые я буду использовать, гарантированно будут в формате ascii, поэтому я думаю, что пока буду придерживаться первого метода. Я буду иметь в виду, что toupper
зависит от локали, когда / если мне это нужно.