У компиляторов обычно есть специальные оптимизации для строк? - PullRequest
1 голос
/ 01 сентября 2011

Часто вы видите такие вещи, как

std::map<std::string, somethingelse> m_named_objects;

или

std::string state;

//...

if(state == "EXIT")
   exit();
else if(state == "california")
   hot();

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

Могут ли современные компиляторы (msvc, g ++ и т. Д.) Обычно использовать специальные оптимизации для таких случаев?Или этого следует избегать из-за плохой работы или по другим причинам?

Ответы [ 4 ]

6 голосов
/ 01 сентября 2011

Могут ли современные компиляторы (msvc, g ++ и т. Д.) Обычно использовать специальные оптимизации для этих типов случаев?

Насколько я знаю, компиляторы не проводят такого рода оптимизации. Это определенно не «стандартная» оптимизация.

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

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

enum State
{
    Alabama,
    Alaska,
    Arizona,
    Arkansas, 
    California,
    Colorado,
    Connecticut,
    Delaware,
    // ... More
};

// ...

State state = California;
if(state == California) { /* true */ }
1 голос
/ 01 сентября 2011

Библиотеки делают.

Компиляторы могли бы оптимизировать, используя псевдоним совместно используемые / идентичные статические строки (при условии, что они действительно обрабатываются как константы).

Все реализации стандартной библиотеки C ++, о которых я знаю, sport «оптимизация небольших строк», что означает, что для небольших строк не требуется дополнительного выделения кучи;Т.е.

std::string a("small");

будет полностью выделено автоматически (в стеке) - в высокооптимизированных случаях, возможно, даже будет выделено регистр (?)


Если вам нужен невероятно быстрый поиск строк и вы можете позволить себе некоторыевремя, потраченное на построение вашей структуры данных, посмотрите на Tries (WP: Trie , Radix_tree )

Что касается вставных замен, то обычно лот можно получить, используя правильно настроенную хэш-карту вместо карты на основе RB-дерева:

std::map<std::string, somethingelse> m_named_objects;

заменить на

std::unordered_map<std::string, somethingelse> m_named_objects;

Будь счастлив

0 голосов
/ 01 сентября 2011

Оптимизация для строк предназначена для библиотек, а не для компиляторов.Если вам нужны строковые идентификаторы, перечисления являются одной из возможностей.Но лучшим вариантом, особенно для печати и отладки, является класс строки идентификатора фиксированной длины.

Он может быть конвертирован в const char * и std::string, но у него будет нулевое распределение памяти.Вместо этого это будет просто обертка вокруг 32-символьного (или как вам угодно) массива.

Самое приятное то, что, поскольку это идентификатор, вас не волнует символьный символ ASCIIсравнения.operator< может просто прочитать 32-символьный массив как 8 uint32_t с или даже как 4 uint64_t с.Все, что вам нужно - это и заказ, а не конкретный заказ.operator== может выполнять аналогичные тесты.

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

Если вам нужны строки длиннее 31 байта (одна для терминатора \0), тогда япредложил бы обрезать строку до размера.Но обрезать от середина данной строки, а не до конца.Начало и конец идентификаторов имеют тенденцию быть более уникальными, чем середина.Вы могли бы даже поместить некоторые специальные символы в усеченную строку, чтобы определить, что это усеченная версия.

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

0 голосов
/ 01 сентября 2011

В приведенных примерах компилятор, как правило, не может оптимизировать, поскольку содержимое зависит от времени выполнения.

std::map<std::string, int> не имеет наиболее желательных рабочих характеристик, так как operator<() на std::string относительно дорог.

...