Быстрое сравнение 64 бит - PullRequest
3 голосов
/ 02 марта 2010

Я работаю над структурой графического интерфейса, где я хочу, чтобы все элементы были идентифицированы с помощью строк ascii длиной до 8 символов (или 7 будет в порядке).

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

Я мог бы использовать реальные строки и strcmp (), но я хочу, чтобы это было действительно быстро (для мобильных устройств), поэтому я подумал об использовании констант char (например, int id = 'BTN1';), чтобы вы были делать единственное сравнение int для проверки идентификатора. Однако 4 символа недостаточно читабельны.

Я попробовал эксперимент, что-то вроде long int id = L'abcdefg ';

... но выглядит так, как будто константы char могут содержать только 4 символа, и единственная вещь, которая дает длинную int char константу, дает вам способность ваших 4 символов быть в два раза шире, а не в два раза больше персонажи. Я что-то здесь упускаю?

Я хочу, чтобы человеку, пишущему код клиента, было легко. Графический интерфейс хранится в xml, поэтому идентификаторы загружаются из строк, но в клиентском коде будут записаны константы для сравнения.

Итак, в общем и целом, я ищу кроссплатформенный способ быстрого сравнения 7-8 символов, есть идеи?

Ответы [ 6 ]

4 голосов
/ 02 марта 2010

Вы уверены, что это не преждевременная оптимизация? Вы профилировали другую структуру GUI, которая является медленной чисто из сравнения строк? Почему вы так уверены, что сравнение строк будет слишком медленным? Конечно, вы не делаете , что сравнивает много строк. Кроме того, учтите, что strcmp должен иметь почти оптимальную реализацию, возможно написанную на ассемблере, специально предназначенном для процессора, для которого вы компилируете.

В любом случае, другие платформы просто используют именованные целые числа, например:

static const int MY_BUTTON_ID = 1;

Вы могли бы рассмотреть это вместо того, чтобы полностью избежать проблемы со строками. В качестве альтернативы, вы можете просто написать вспомогательную функцию для преобразования const char [9] в 64-битное целое число. Это должно принимать строку с нулевым символом в конце «как есть» до 8 символов (при условии, что вы собираетесь выбросить нулевой символ). Затем ваша программа передает 64-битные целые числа, но программист имеет дело со строками.

Редактировать: вот быстрая функция, которая превращает строку в число:

__int64 makeid(const char* str)
{
    __int64 ret = 0;
    strncpy((char*)&ret, str, sizeof(__int64));
    return ret;
}
4 голосов
/ 02 марта 2010

Одна возможность состоит в том, чтобы определить ваши идентификаторы как объединение 64-битного целого числа и 8-символьной строки:

union ID {
  Int64 id;      // Assuming Int64 is an appropriate typedef somewhere
  char name[8];
};

Теперь вы можете делать такие вещи как:

ID id;
strncpy(id.name, "Button1", 8);
if (anotherId.id == id.id) ...
1 голос
/ 02 марта 2010

Понятие интернирование строк может быть полезно для этой проблемы, превращая сравнение строк в сравнение указателей.

1 голос
/ 02 марта 2010

Легко получить предварительно прокатанные компоненты

двоичное дерево поиска для победы - вы получаете красно-черное дерево из большинства реализаций STL набора и карты, так что вы можете рассмотреть это.

Навязчивые версии контейнеров STL работают НАМНОГО лучше, когда вы перемещаете узлы контейнеров много (в общем случае) - однако у них довольно много предостережений.

Особое мнение - Первая альтернатива

На вашем месте я бы использовал 64-битный целочисленный тип, упаковал его в навязчивый контейнер и использовал бы библиотеку, предоставляемую boost. Однако, если вы новичок в такого рода вещах, тогда используйте stl :: map, что концептуально проще понять, и у него меньше шансов утечки ресурсов, так как есть больше литературы и руководств для этих типов контейнеров и лучших практик.

Альтернатива 2

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

// WidgetHandle is a polymorphic base class (i.e., it has a virtual method),
// and foo::Luv implement WidgetHandle's interface (public inheritance)
foo::WidgetHandle * LuvComponent = 
          Factory.CreateComponent<foo::Luv>( "meLuvYouLongTime");
....

.... // in different function
foo::WidgetHandle * LuvComponent = 
          Factory.RetrieveComponent<foo::Luv>("meLuvYouLongTime");

Альтернатива 2 - это общая идиома для IPC, вы создаете тип IPC, скажем, канал в одном процессе, и вы можете попросить ядро ​​получить другой конец канала по имени.

0 голосов
/ 02 марта 2010

В C ++ 0x вы сможете использовать определяемые пользователем строковые литералы , чтобы вы могли добавить что-то вроде 7chars..id или "7chars.."id:

template <char...> constexpr unsigned long long operator ""id();
constexpr unsigned long long operator ""id(const char *, size_t);

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

0 голосов
/ 02 марта 2010

Я вижу различие между легко читаемыми идентификаторами в вашем коде и передаваемым представлением.

Не могли бы вы использовать перечислимый тип (или большой заголовочный файл констант) для представления идентификатора? Имена перечислимых типов могут быть настолько длинными и значимыми, насколько вы пожелаете, и все же вмещать (я предполагаю) пару байтов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...