У меня есть класс, которым управляет std::shared_ptr
. Этот класс имеет хеш и все операторы ==
, <
и т.д. Для простоты предположим, что это класс int
. Что мне нужно, так это реестр всех int
, используемых в настоящее время, который не будет поддерживать их в рабочем состоянии дольше, чем необходимо, и имеет быстрый (быстрый, чем линейный) поиск. Это будет использоваться, чтобы гарантировать, что я не создам два разных объекта int
с одним и тем же номером, например. прежде чем создавать новый 42
, я проверю, существует ли уже 42
в реестре. Кажется, я хочу что-то вроде Java WeakHashMap
?
Одно из возможных решений — использовать std::unordered_set<std::shared_ptr<int>>
и периодически перебирать набор и удалять все элементы, у которых shared_ptr::use_count()
равно 1. Это работает, но не идеально, поскольку объекты остаются живыми дольше, чем им нужно.
Или я мог бы использовать std::vector<std::weak_ptr<int>>
, который освобождал бы немедленно, но требовал бы итерации по всему вектору каждый раз, когда я хочу увидеть, существует ли конкретный int
(медленно).
std::unordered_set<std::weak_ptr<int>>
удовлетворит обоим моим требованиям, за исключением того факта, что хэши должны будут измениться после истечения срока действия weak_ptr
, и "Container elements may not be modified since modification could change an element's hash and corrupt the container"
.
Есть ли контейнер с быстрым поиском, который может обрабатывать изменяющиеся хэши? Имейте в виду, что ему не нужно находить элементы, которые изменились, он просто не должен быть поврежден ими.
std::map<int, std::weak_ptr<int>>
требует хранения копииint
в качестве ключа, который не будет освобожден, когда все ссылки исчезнут. @SergeyDyshko, читаю это сейчас. - person imMAW   schedule 25.07.2020std::multimap<hash, std::weak_ptr<int>>
может помочь (мультимап в случае коллизии хэшей). - person imMAW   schedule 25.07.2020std::unordered_set<std::weak_ptr<int>>
, я не хочу, чтобы хэш изменился, я не смогу вычислить старый хеш. Мне нужно предоставитьunordered_set
хеш-функцию, которая принимаетstd::weak_ptr<int>
. Я мог бы реализовать это, выполнив:if unexpired, return the hash of the int. else if expired, return 0
. По истечении срока действияweak_ptr
хеш-функция не сможет получить целое число и не сможет вычислить старый хэш. Но кажется, чтоunordered_set
столкнется с проблемами, если я использую эту хеш-функцию. - person imMAW   schedule 25.07.202042
на карте перед ее созданием, по вашей аналогии42
является объектом. Так как же узнать, существует ли объект уже до его создания? - person super   schedule 25.07.202042
для поиска, а затем немедленно уничтожить его, если он уже существует. Не идеально, но в любой момент будет максимум один ненужный объект, занимающий память. Что касается изменяющегося хэша - хэш объекта вset
может быть пересчитан в любое время, когдаset
пожелает это сделать, и он ожидает, что хэш каждый раз будет одним и тем же. Смотрите самый нижний ответ здесь для уточнения: вычисление хэша должно быть стабильным title="почему 32769-я вставка не работает в stdunordered set"> stackoverflow.com/questions/50402508/ - person imMAW   schedule 25.07.2020std::unordered_set<std::weak_ptr<int>>
«объект вset
» являетсяstd::weak_ptr<int>
, поэтомуunordered_set
будет ожидать, чтоstd::weak_ptr<int>
будет хешировать точно одно и то же каждый раз, когда он хэшируется. При вставке моя хеш-функция сможет правильно хешироватьweak_ptr to 42
, но если она захочет перехешировать после того, как станетweak_ptr to nothing
, я не смогу вернуть правильный хэш. - person imMAW   schedule 25.07.2020std::multimap<hash, std::weak_ptr<int>>
решит все проблемы. По сути, он кэширует хеш, поэтому всякий раз, когда он хочет пересчитать хеш, ему не нужно проходить через weak_ptr. Это просто означает, что мне нужно вручную вызывать хеш во время вставки/поиска, а не позволять контейнеру вызывать хэш за меня. - person imMAW   schedule 25.07.2020