Название: оптимальный доступ к элементам ассоциативных контейнеров Отправлено: kambala от Июль 27, 2012, 22:24 Здравствуйте. Имеются разные QHash и QMap (ключи – числа, строки, есть даже пара строк, всего контейнеров чуть больше 10), в которых хранятся как «небольшие» структуры (3-5 полей), так и «большие» (15-20 полей). Количество элементов не очень большое – примерно от 500 до 2500. Сейчас доступ к контейнерам осуществляется через статические методы класса (сам контейнер является статической переменной-неуказателем в методе), возвращается указатель на контейнер.
Раньше я получал доступ к элементам по ключу через value(), но этот метод возвращает копию объекта, а не ссылку. Недавно поменял это всё на operator[] чтобы получать ссылки и не расходовать память на ненужные копии, но сейчас заметил, что в документации не рекомендуют использовать такой подход: Цитировать In general, we recommend that you use contains() and value() rather than operator[]() for looking up a key in a hash. The reason is that operator[]() silently inserts an item into the hash if no item exists with the same key (unless the hash is const) но это связано лишь со случаями когда ключа не существует, а у меня такие ситуации очень и очень маловероятны (все ключи известны заранее). Но является ли это хорошим подходом? Да и код имеет вид MyClass::myContainer()->operator[](key).someField (будет ли лучше/быстрее (*MyClass::myContainer())[key].someField? или лучше возвращать ссылки из методов вместо указателей?).Заметил ещё методы find() и constFind(), возвращающие итераторы, из которых уже можно получить ссылку на значение, но будет ли это эффективнее, чем operator[]? А может выгоднее хранить в контейнерах не сами элементы, а лишь указатели на них? Да, и данные в контейнерах не меняются и «живут» на протяжении всего жизненого цикла программы, если это имеет значение. Название: Re: оптимальный доступ к элементам ассоциативных контейнеров Отправлено: alexis031182 от Июль 27, 2012, 23:29 Я бы хранил в ассоциативных контейнерах лишь указатели, а сами элементы в списке, либо вообще просто в массиве. Если количество элементов известно заранее и не предполагается изменений, то массив лучше организовать в стеке. Будет ещё чуть быстрее. Я для себя проводил сравнение. Стековый вариант на 100000 lookup'ов выиграл на моей машине 10-20 мс.
Название: Re: оптимальный доступ к элементам ассоциативных контейнеров Отправлено: kambala от Июль 27, 2012, 23:45 хранить массив в стеке не получится, т.к. хоть количество элементов и известно, но оно не является константой, забитой в код.
а зачем вообще дополнительно хранить элементы в массиве? почему нельзя сделать чтобы они просто «висели в воздухе»? Код из-за расположения элементов массива в памяти подряд? Название: Re: оптимальный доступ к элементам ассоциативных контейнеров Отправлено: alexis031182 от Июль 28, 2012, 00:20 хранить массив в стеке не получится, т.к. хоть количество элементов и известно, но оно не является константой, забитой в код. Значит больше подходит под мою задачу: у меня фиксированное кол-во элементов. Я организовывал даже compile-time контейнер, но из-за того, что строковые ключи приходилось писать в виде "'m','y','k','e','y'", отказался от этой затеи - уж очень коряво выглядело. Впрочем, скорость lookup'а была очень высокой.а зачем вообще дополнительно хранить элементы в массиве? почему нельзя сделать чтобы они просто «висели в воздухе»? Это для стекового варианта. В принципе, то что ключи будут меняться - не проблема, главное знать заранее их максимально возможное количество. Ну и конечно согласиться с некоторым перерасходом памяти. В общем нужно выбрать что важнее: скорость или компактность.из-за расположения элементов массива в памяти подряд? Qt-шные контейнеры используют выравнивание в памяти для элементов.Название: Re: оптимальный доступ к элементам ассоциативных контейнеров Отправлено: kambala от Июль 28, 2012, 01:22 меня больше интересует не скорость или расход памяти на хранение (с этим всё нормально), а именно вытаскивание элемента из контейнера. значит если хранить в контейнерах указатели (которые «висят в воздухе»), то можно спокойно использовать value() и ни о чём не беспокоиться?
Название: Re: оптимальный доступ к элементам ассоциативных контейнеров Отправлено: alexis031182 от Июль 28, 2012, 02:14 меня больше интересует не скорость или расход памяти на хранение (с этим всё нормально), а именно вытаскивание элемента из контейнера. Я как раз и говорил о lookup'е (поиске элемента) с выдачей результата.значит если хранить в контейнерах указатели (которые «висят в воздухе»), то можно спокойно использовать value() и ни о чём не беспокоиться? Копирование указателя конечно дешевле, нежели копирование объекта какого-либо класса. И преимуществ от выравнивания памяти для выдачи элемента нет никаких: всё равно будет вызван конструктор копирования. Честно говоря, не могу понять, почему QHash не предоставляет возврат по ссылке. Хотя бы для версии value() с дефолтным значением могли бы сделать.З.Ы. Придётся "вручную" удалять объекты из контейнера, если он содержит лишь указатели. Название: Re: оптимальный доступ к элементам ассоциативных контейнеров Отправлено: kambala от Июль 28, 2012, 08:48 хорошо, спасибо
Название: Re: оптимальный доступ к элементам ассоциативных контейнеров Отправлено: Igors от Июль 28, 2012, 12:56 Да, и данные в контейнерах не меняются и «живут» на протяжении всего жизненого цикла программы, если это имеет значение. Это имеет значение. Ссылка возвращенная из QHash станет невалидной при добавлении новых элементов (rehash). Про QMap не знаю а вот std::map все хорошо - адрес не изменится при добавлении, и это бывает важно. А может выгоднее хранить в контейнерах не сами элементы, а лишь указатели на них? Если операции вставки-удаления крайне редки, то вообще имеет смысл хранить сортированный массив указателей и использовать binary_search, lower_bound. Это экономит память значительно, т.к. ассоциативный контейнер требует довольно жирных доп данных для каждого элемента. Поиск в сортированном массиве может и проигрывает хешу, но может и нет (напр хеш-ключ мудреный). Но во всяком случае он несколько быстрее чем в std::map/setЕсли не хочется уходить от стандартных, то (для чтения) грамотно использовать итератор и потом возвращать указатель на данные или NULL Название: Re: оптимальный доступ к элементам ассоциативных контейнеров Отправлено: DmitryM от Июль 28, 2012, 13:42 std::set использует бинарное дерево, так что поиск такой же как у упорядоченного массива.
Название: Re: оптимальный доступ к элементам ассоциативных контейнеров Отправлено: kambala от Август 01, 2012, 18:29 после того, как перевел все контейнеры на хранение указателей, вспомнил наконец почему я отказался от этой идеи в начале: периодически я обращаюсь к несуществующим ключам в других структурах данных, получаяя default value, у которой поля-числа инициализированы заданным значением, что есть правильно. а вот в случае с указателями идет обращение к нулевому указателю, где программа и падает... хорошо, что существуют системы контроля версий :)
|