![]() |
|
Модераторы: Daevaorn |
![]()
|
|
| mr.DUDA |
|
|||
|
3D-маньяк ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 8244 Регистрация: 27.7.2003 Где: город-герой Минск Репутация: 25 Всего: 232 |
Вопрос: останется ли итератор "iter" валидным ? Т.е. можно ли будет обращаться к нему по "*iter" ? Тот же самый вопрос по контейнерам "set", "multimap", "list". Тот-же вопросик -- для случая если удалить элемент из контейнера ? -------------------- ![]() |
|||
|
||||
| DENNN |
|
||||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3878 Регистрация: 27.3.2002 Где: Москва Репутация: 1 Всего: 43 |
В общем случае - нет. Мне неизвестно, оговаривает ли стнадарт способ хранения эл-ов в виде связанного списка, но даже если элементы храняться именно так, то такой код потенциальный источник ошибок. Не только потому, что во втором цикле необходимо проверить все возвращаемые пары оператором my_map.insert(map_t::value_type(i, i)); на предмет того, выполнена ли вставка в контейнер нового элемента, но и потому что ассоциативные контейнеры в будущем захочется заменить хешированными и все через полгода окажется что программа не всегда работает верно. Кроме того, даже если хранение реализовано в виде связанного списка, то нестандартный аллокатор мог как-то хитро перерасперделить память и использование такого итератора опять же будет рискованно (наверно по этой причине стандарт все же не регламентирует такой способ хранения).
C set ситуация полностью анналогична. C multimap однозначно нельзя, ведь когда в контейнер добавиться копия нового элемента, то возможно старый итератор не сможет корректно выполнить операции перехода, да и сам элемент может "переместиться". С list можно, но осторожно |
||||
|
|||||
| mr.DUDA |
|
||||
|
3D-маньяк ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 8244 Регистрация: 27.7.2003 Где: город-герой Минск Репутация: 25 Всего: 232 |
DENNN, получается я не смогу использовать систему глобальных идентификаторов, при которой ID'ом является итератор, а строковым эквивалентом - значение разыменования "*" итератора ?
Какой из контейнеров STL (или какая реализация STL) поддерживает алгоритм хеширования, или это
просто пример ? И, последнее, в доке по стандарту STL говорится что вставка и удаление элемента в ассоциативные контейнеры не приводит к изменению валидности существующих итераторов -- относится ли это только к HP-версии STL ? -------------------- ![]() |
||||
|
|||||
| DENNN |
|
||||||||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3878 Регистрация: 27.3.2002 Где: Москва Репутация: 1 Всего: 43 |
Официально, хешированные контейнеры не входят в стандарт STL, но поставляются со многими реализациями.
Честно говоря да, но обычно, для многих задач такие контейнеры оказываются в среднем более производительные, чем обычные ассоциативные, если, конечно, хеш-функция подобрана удачно.
Если так говориться, значит это правило должно выполняться для любой реализации библиотеки. Естестыенно, если ты удаляешь элемент, на который указывает итератор или все элементы, эквивалентные этому, то в твоей программе все равно появиться источник ошибок. В достаточно большом алгоритме это будет трудно обнаружимая и не всегда появляющаяся ошибка.
Немного странный способ сопоставления ID его данным. Скажи какие задачи ты пытаешься реализовать таким образом и я попробую написать свой код. P.S. AFX- не очень хороший идентификатор, так как легко перепутать с MFC-ми макросами. |
||||||||
|
|||||||||
| mr.DUDA |
|
|||
|
3D-маньяк ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 8244 Регистрация: 27.7.2003 Где: город-герой Минск Репутация: 25 Всего: 232 |
DENNN, нужно создать систему (чем-то схожую с виндошными ATOM'ами) глобальных (в рамках одного процесса) идентификаторов (далее - ID'ов). Требования к системе:
Цель данной системы - предоставить возможность сопоставить любому объекту уникальный идентификатор, сохраняемый и загружаемый в/из файла (потока), с возможностью динамической регистрации и поиска ID по строке. Это даст возможность, например, хранить объекты в ассоциативном списке, с ключом-ID'ом (а не строкой), с возможностью быстро получить строку по значению ID; также можно будет свободно проектировать открытую систему с динамически подключаемыми модулями, не зная, например, значение кода сообщения, передаваемого в главный модуль из подключаемого, но зная строковый эквивалент (и это не будет тормозить всю программу, т.к. ID регистрируется только один раз, и далее используется очень быстрая операция сравнения). Эта система должна работать с максимальной скоростью, конкретные типы данных (строка, ID и контейнер) могут быть произвольными. До этого я попытался реализовать то же самое с помощью контейнера CMapStringToPtr, и специально написанного класса _AFX_ID (хранящего строку ID'a). Собственно ID'ом был указатель на _AFX_ID, а сами объекты _AFX_ID хранились в вышеуказанном контейнере. Итераторы выбрал т.к. в HP-версии STL они занимают минимум места (инкапсулируют указатель и ничего более), обеспечивают очень быструю операцию разименования (и получения строки ID'а) и сравнения (сравнивается указатель с указателем). А то, что используется "AFX" в именах типов -- это не более чем старая привычка Это сообщение отредактировал(а) mr.DUDA - 19.8.2003, 12:02 -------------------- ![]() |
|||
|
||||
| mr.DUDA |
|
|||
|
3D-маньяк ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 8244 Регистрация: 27.7.2003 Где: город-герой Минск Репутация: 25 Всего: 232 |
В обчем, можно было бы делать IDы не итераторами, только будет тормознутее.
-------------------- ![]() |
|||
|
||||
| DENNN |
|
||||||||||||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3878 Регистрация: 27.3.2002 Где: Москва Репутация: 1 Всего: 43 |
Все же какова ситуация: ID сопоставляется строка или идентификатор некоторого объекта может быть представлен как ID так и строкой? Мне все же кажется, что видя вся картину в целом, можно выбрать более простой путь.
ну задай их в своем шаблоне. Если ты хочешь сделать супер-пупер универсальную систему, хранящую любые вообще объекты одновременно, то придеться хранить указатели на них в глобальной памяти, если просто экземпляр такого класса хранит однотипные указатели, то введи этот параметр в шаблон. Еще я не понял, зачем хранить в контейнере bool?
Если для последнего варианта, то шаблон такого класса-хранилища будет выглядеть примерно так:
Предупреждаю сразу, вбито просто с клавиатуры, поэтому вохможны (и даже очень возможны) синтаксические ошибки, пропущенные двоеточия и т.п. - все таки нахаляву тружусь Стороки кода
лучше усложнить, чтоб обработать ситуацию, когда в первый контейнер пара добавлена, а во второй нет. Самое главное: для твоих объектов T_ID и T_str_ID должна быть верно определена операция "<", конечно можно добавить в шаблон параметр по умолчанию для использования предикатов, но дело не в этом, а в том, что два идентификатора - это гемор. Еще большая проблема с тем, что различные текстовые контейнеры, обозначенные у меня как T_str_ID могут по разному сравнивать прописные и строчные буквы. Вообще в целом, задание не формализовано, поэтому и весь код смотрится как бред. Это сообщение отредактировал(а) DENNN - 19.8.2003, 14:23 |
||||||||||||
|
|||||||||||||
| DENNN |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3878 Регистрация: 27.3.2002 Где: Москва Репутация: 1 Всего: 43 |
Обрати внимание на использование while в строках
Так как на самом деле в контейнере может храниться много одинаковых строк, то лучше использовать цикл совместно с advance или что-то подобное. Но! Мы считаем что строка может соответствовать только одному идентифиактору (и кстати в моем коде нигде не проверяется это условие при добавлении нового элемента). |
|||
|
||||
| mr.DUDA |
|
|||
|
3D-маньяк ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 8244 Регистрация: 27.7.2003 Где: город-герой Минск Репутация: 25 Всего: 232 |
Ok, расскажу поподробней (выше я привел требования только к самой системе идентификаторов, что действительно м.б. недостаточным для понимания, что же нужно сделать).
Суть задачи сводится к тому, чтобы получить возможность сопоставить чему-либо (не обязательно объекту, и не обязательно объекту в контейнере Это даст наглядность, безопасность (не нужно будет согласовывать по 100 раз числовые IDы в разных плагинах -- а это пришлось бы делать, т.к. вся программа построена на плагинах, постоянно взаимодействующих между собой с активным использованием идентификаторов), и позволит упростить множество побочных задач (таких, как например доступ к отдельным полям объекта по ID, перечисление таких полей-свойств в виде списка имён, запись и чтение объекта в формате XML, функции модифицируемые извне с пом. запрета именованных (читай-идентифицируемых) блоков кода или вставки вызова др. подобной функции между именованными блоками, и т.д. Идентификаторы (далее - ID) будут очень часто подвергаться сравнению (с другими идентификаторами). Строки сравниваются медленно и занимают слишком много места. Значит, нужно найти решение, при котором строка-идентификатор будет ОДИН раз связана с простым типом данных (например, DWORD) -- т.н. "регистрация ID'а", и все последующие операции по хранению, сравнению и передаче ID будут проводиться не над строкой, а над ее "быстрым" эквивалентом. Обязательное условие -- обеспечить возможность получения строки по значению ID. Храниться пары "ID<=>строка" должны в глобальном объекте, "представляющем" глобальную область видимости текущего модуля (во завернул). Коротко насчет модулей. Главный модуль -- это EXE. Остальные модули -- подключаемые DLL (плагины). У каждого модуля есть свой объект CModuleGlobal; но при подключении DLL, последняя "передаёт" все свои зарегистрированные ID'ы главному модулю (чтобы обеспечить единственность контейнера ID'ов); свой контейнер игнорируется и все вызовы IdRegister, IdLookup и т.п. перенаправляются в главный модуль (в примере это не показано, чтобы не запутать и без того запутанный код ЗЫ, это всё должно входить в ядро MathCAD-подобного приложения с открытой архитектурой. -------------------- ![]() |
|||
|
||||
| RAN |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 709 Регистрация: 14.3.2003 Где: Щёлково Моск.обл. Репутация: 5 Всего: 6 |
COM не подходит?
|
|||
|
||||
| mr.DUDA |
|
|||
|
3D-маньяк ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 8244 Регистрация: 27.7.2003 Где: город-герой Минск Репутация: 25 Всего: 232 |
COM может и подходит, но слишком замороченный и всё равно придется половину задуманного делать самостоятельно
Я поначалу думал делать плагины объектами COM, но вот в чем вся фишка: пока начнешь собственно писать плагин, все зубы сломаешь об интерфейсы, маршаллинг и прочие прокси-стабы -------------------- ![]() |
|||
|
||||
| Fantasist |
|
||||
|
Лентяй ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1517 Регистрация: 24.3.2002 Репутация: 4 Всего: 41 |
Не понял, как COM связан с этой задачей? А почему не сделать бы map<string,pointer>? Вот тебе указатель будет и ID который быстро сравнивать, и при разименовании получаешь значение. Для красоты его можно завернуть в соответсвующую структуру.
Для этого существует два способа: 1. pointer сделать структурой типа: struct IDPointer { pointer ptr; string name; pointer operator pointer() {return ptr;}; operator->() {return ptr;}; } То есть хранить сразу с указателем и его имя. 2. Взять класс типа bimap. Один из вариантов которых лежит на codeproject -------------------- Волны гасят ветер... |
||||
|
|||||
| mr.DUDA |
|
|||
|
3D-маньяк ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 8244 Регистрация: 27.7.2003 Где: город-герой Минск Репутация: 25 Всего: 232 |
Первый вариант (со структурой) не очень катит тем, что строку хранить придется 2 раза - в ключе map'а и внутри структуры.
Если ничего не получится придумать, придется юзать bimap. -------------------- ![]() |
|||
|
||||
| Fantasist |
|
|||
|
Лентяй ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1517 Регистрация: 24.3.2002 Репутация: 4 Всего: 41 |
Во-первых, чем это плохо? Не думаю, что у тебя на мегабайты этих ключей. Во-вторых, если это так, или просто хочеться обеспечить тесную взаимосвязь, то хранить можно указатель или ссылку строку. -------------------- Волны гасят ветер... |
|||
|
||||
| mr.DUDA |
|
|||
|
3D-маньяк ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 8244 Регистрация: 27.7.2003 Где: город-герой Минск Репутация: 25 Всего: 232 |
Всё. Итераторы в качестве ID юзать не получится, т.к. их (итераторы) нельзя (в свою очередь) хранить в контейнере. Так что придется делать по старой схеме (что-то наподобие того, что предлагает Fantasist):
Храним в словаре пару "строка<=>указатель на структуру _AFX_ID", получаем ID по строке через "mapIDs.find", получаем строку по ID через IdGetString(id). ИМХО, через итераторы изящнее получалось Это сообщение отредактировал(а) mr.DUDA - 19.8.2003, 22:04 -------------------- ![]() |
|||
|
||||
![]()
|
| Правила форума "С++:Общие вопросы" | |
|
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |