Russian Qt Forum
Ноябрь 24, 2024, 02:51
Добро пожаловать,
Гость
. Пожалуйста,
войдите
или
зарегистрируйтесь
.
Вам не пришло
письмо с кодом активации?
1 час
1 день
1 неделя
1 месяц
Навсегда
Войти
Начало
Форум
WIKI (Вики)
FAQ
Помощь
Поиск
Войти
Регистрация
Russian Qt Forum
>
Forum
>
Qt
>
Общие вопросы
>
оптимальный доступ к элементам ассоциативных контейнеров
Страниц: [
1
]
Вниз
« предыдущая тема
следующая тема »
Печать
Автор
Тема: оптимальный доступ к элементам ассоциативных контейнеров (Прочитано 6018 раз)
kambala
Джедай : наставник для всех
Offline
Сообщений: 4747
оптимальный доступ к элементам ассоциативных контейнеров
«
:
Июль 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[]?
А может выгоднее хранить в контейнерах не сами элементы, а лишь указатели на них? Да, и данные в контейнерах не меняются и «живут» на протяжении всего жизненого цикла программы, если это имеет значение.
Записан
Изучением C++ вымощена дорога в Qt.
UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
alexis031182
Гость
Re: оптимальный доступ к элементам ассоциативных контейнеров
«
Ответ #1 :
Июль 27, 2012, 23:29 »
Я бы хранил в ассоциативных контейнерах лишь указатели, а сами элементы в списке, либо вообще просто в массиве. Если количество элементов известно заранее и не предполагается изменений, то массив лучше организовать в стеке. Будет ещё чуть быстрее. Я для себя проводил сравнение. Стековый вариант на 100000 lookup'ов выиграл на моей машине 10-20 мс.
Записан
kambala
Джедай : наставник для всех
Offline
Сообщений: 4747
Re: оптимальный доступ к элементам ассоциативных контейнеров
«
Ответ #2 :
Июль 27, 2012, 23:45 »
хранить массив в стеке не получится, т.к. хоть количество элементов и известно, но оно не является константой, забитой в код.
а зачем вообще дополнительно хранить элементы в массиве? почему нельзя сделать чтобы они просто «висели в воздухе»?
Код
C++ (Qt)
QHash
<
int
,
Item
*>
hash
;
Item
*
item
=
new
Item
;
...
hash
[
0
]
=
item
;
из-за расположения элементов массива в памяти подряд?
Записан
Изучением C++ вымощена дорога в Qt.
UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
alexis031182
Гость
Re: оптимальный доступ к элементам ассоциативных контейнеров
«
Ответ #3 :
Июль 28, 2012, 00:20 »
Цитата: kambala от Июль 27, 2012, 23:45
хранить массив в стеке не получится, т.к. хоть количество элементов и известно, но оно не является константой, забитой в код.
Значит больше подходит под мою задачу: у меня фиксированное кол-во элементов. Я организовывал даже compile-time контейнер, но из-за того, что строковые ключи приходилось писать в виде "'m','y','k','e','y'", отказался от этой затеи - уж очень коряво выглядело. Впрочем, скорость lookup'а была очень высокой.
Цитата: kambala от Июль 27, 2012, 23:45
а зачем вообще дополнительно хранить элементы в массиве? почему нельзя сделать чтобы они просто «висели в воздухе»?
Это для стекового варианта. В принципе, то что ключи будут меняться - не проблема, главное знать заранее их максимально возможное количество. Ну и конечно согласиться с некоторым перерасходом памяти. В общем нужно выбрать что важнее: скорость или компактность.
Цитата: kambala от Июль 27, 2012, 23:45
из-за расположения элементов массива в памяти подряд?
Qt-шные контейнеры используют выравнивание в памяти для элементов.
Записан
kambala
Джедай : наставник для всех
Offline
Сообщений: 4747
Re: оптимальный доступ к элементам ассоциативных контейнеров
«
Ответ #4 :
Июль 28, 2012, 01:22 »
меня больше интересует не скорость или расход памяти на хранение (с этим всё нормально), а именно вытаскивание элемента из контейнера. значит если хранить в контейнерах указатели (которые «висят в воздухе»), то можно спокойно использовать value() и ни о чём не беспокоиться?
Записан
Изучением C++ вымощена дорога в Qt.
UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
alexis031182
Гость
Re: оптимальный доступ к элементам ассоциативных контейнеров
«
Ответ #5 :
Июль 28, 2012, 02:14 »
Цитата: kambala от Июль 28, 2012, 01:22
меня больше интересует не скорость или расход памяти на хранение (с этим всё нормально), а именно вытаскивание элемента из контейнера.
Я как раз и говорил о lookup'е (поиске элемента) с выдачей результата.
Цитата: kambala от Июль 28, 2012, 01:22
значит если хранить в контейнерах указатели (которые «висят в воздухе»), то можно спокойно использовать value() и ни о чём не беспокоиться?
Копирование указателя конечно дешевле, нежели копирование объекта какого-либо класса. И преимуществ от выравнивания памяти для выдачи элемента нет никаких: всё равно будет вызван конструктор копирования. Честно говоря, не могу понять, почему QHash не предоставляет возврат по ссылке. Хотя бы для версии value() с дефолтным значением могли бы сделать.
З.Ы. Придётся "вручную" удалять объекты из контейнера, если он содержит лишь указатели.
Записан
kambala
Джедай : наставник для всех
Offline
Сообщений: 4747
Re: оптимальный доступ к элементам ассоциативных контейнеров
«
Ответ #6 :
Июль 28, 2012, 08:48 »
хорошо, спасибо
Записан
Изучением C++ вымощена дорога в Qt.
UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Igors
Джедай : наставник для всех
Offline
Сообщений: 11445
Re: оптимальный доступ к элементам ассоциативных контейнеров
«
Ответ #7 :
Июль 28, 2012, 12:56 »
Цитата: kambala от Июль 27, 2012, 22:24
Да, и данные в контейнерах не меняются и «живут» на протяжении всего жизненого цикла программы, если это имеет значение.
Это имеет значение. Ссылка возвращенная из QHash станет невалидной при добавлении новых элементов (rehash). Про QMap не знаю а вот std::map все хорошо - адрес не изменится при добавлении, и это бывает важно.
Цитата: kambala от Июль 27, 2012, 22:24
А может выгоднее хранить в контейнерах не сами элементы, а лишь указатели на них?
Если операции вставки-удаления крайне редки, то вообще имеет смысл хранить сортированный массив указателей и использовать binary_search, lower_bound. Это экономит память значительно, т.к. ассоциативный контейнер требует довольно жирных доп данных для каждого элемента. Поиск в сортированном массиве может и проигрывает хешу, но может и нет (напр хеш-ключ мудреный). Но во всяком случае он несколько быстрее чем в std::map/set
Если не хочется уходить от стандартных, то (для чтения) грамотно использовать итератор и потом возвращать указатель на данные или NULL
Записан
DmitryM
Гость
Re: оптимальный доступ к элементам ассоциативных контейнеров
«
Ответ #8 :
Июль 28, 2012, 13:42 »
std::set использует бинарное дерево, так что поиск такой же как у упорядоченного массива.
Записан
kambala
Джедай : наставник для всех
Offline
Сообщений: 4747
Re: оптимальный доступ к элементам ассоциативных контейнеров
«
Ответ #9 :
Август 01, 2012, 18:29 »
после того, как перевел все контейнеры на хранение указателей, вспомнил наконец почему я отказался от этой идеи в начале: периодически я обращаюсь к несуществующим ключам в других структурах данных, получаяя default value, у которой поля-числа инициализированы заданным значением, что есть правильно. а вот в случае с указателями идет обращение к нулевому указателю, где программа и падает... хорошо, что существуют системы контроля версий
Записан
Изучением C++ вымощена дорога в Qt.
UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Страниц: [
1
]
Вверх
Печать
« предыдущая тема
следующая тема »
Перейти в:
Пожалуйста, выберите назначение:
-----------------------------
Qt
-----------------------------
=> Вопросы новичков
=> Уроки и статьи
=> Установка, сборка, отладка, тестирование
=> Общие вопросы
=> Пользовательский интерфейс (GUI)
=> Qt Quick
=> Model-View (MV)
=> Базы данных
=> Работа с сетью
=> Многопоточное программирование, процессы
=> Мультимедиа
=> 2D и 3D графика
=> OpenGL
=> Печать
=> Интернационализация, локализация
=> QSS
=> XML
=> Qt Script, QtWebKit
=> ActiveX
=> Qt Embedded
=> Дополнительные компоненты
=> Кладовая готовых решений
=> Вклад сообщества в Qt
=> Qt-инструментарий
-----------------------------
Программирование
-----------------------------
=> Общий
=> С/C++
=> Python
=> Алгоритмы
=> Базы данных
=> Разработка игр
-----------------------------
Компиляторы и платформы
-----------------------------
=> Linux
=> Windows
=> Mac OS X
=> Компиляторы
===> Visual C++
-----------------------------
Разное
-----------------------------
=> Новости
===> Новости Qt сообщества
===> Новости IT сферы
=> Говорилка
=> Юмор
=> Объявления
Загружается...