Скажем, например, на элемент ссылаются из нескольких карт, например, имя карты для элемента, адрес карты для элемента и возраст карты для элемента. Теперь кто-то ищет элемент, например, по имени, и теперь хочет удалить его со всех трех карт?
На ум приходит несколько решений:
1) Самый прямой. Найдите элемент в названии карты элемента, затем найдите обе другие карты, чтобы найти элемент в них, а затем удалите запись элемента во всех трех.
2) Храните слабые указатели на всех трех картах. Храните общий указатель где-нибудь, в лучшем случае, возможно, даже в самом элементе. Найдя элемент на одной карте, удалите элемент. При попытке получить доступ к элементу с других карт и обнаружении, что слабые указатели не могут быть преобразованы в общие указатели, удалите запись.
3) Используйте навязчивые карты. Это имеет то преимущество, что не нужно искать оставшиеся карты, чтобы найти элемент в них. Однако, поскольку объект хранится в нескольких картах, сам элемент не может быть навязчивым — скорее всего элемент должен иметь член, реализующий ловушки.
4) Другие?
Есть ли очень чистое хорошее решение для этого? Я сталкивался с этой проблемой несколько раз …
Несколько мыслей. Решение 1, как правило, является тем, которое естественным образом реализуется по мере роста проекта. Если сам элемент имеет ключевую информацию о других картах, а другие контейнеры являются картами, это, вероятно, вполне приемлемо. Однако, если ключи отсутствуют или если контейнер, например, список, это может стать очень медленным. Решение 2 зависит от реализации слабых указателей и может также оказаться довольно медленным. Решение 3 кажется лучшим, но может быть несколько сложным?
повышение :: multi_index разработан специально для такого случая.
Похоже, вы еще не решили, что управляет временем жизни объекта — это на первом месте. Как только вы это знаете, используйте шаблон наблюдателя. Когда объект должен быть уничтожен, возражающий magaing за время своего существования уведомляет все объекты, которые обертывают карты, содержащие указатели, а затем уничтожает объект.
Наблюдатели могут реализовать общий интерфейс, например так:
class ObjectLifetimeMgr
{
public:
CauseObjDeletion()
{
/.. notify all observers ../
}
private:
list<IObserver*> observers;
};
class IObserver
{
public:
virtual void ObjectDestroyed( Obj* );
};
class ConcreteObserver
{
public:
void ObjectDestroyed( Obj* )
{
/.. delete Obj from map ../
}
};
Или сделать действительно прекрасную работу, которую вы могли бы реализовать делегат C ++, это освобождает наблюдателей от общего базового класса и просто позволяет им зарегистрировать обратный вызов, используя метод-член
Никогда не находил ничего, что могло бы заменить решение 1. В итоге я использовал shared_pointers и удалил флаги в функции удаления (например, DeleteFromMaps(bool map1, bool map2, bool map3)
) в объекте. Вызов, например, из map2, становится, например,
it->DeleteFromMaps(true,false,true);
erase(it);