Мне нужна коллекция, в которой я могу хранить выделенные в куче объекты, имеющие виртуальные функции.
Я знаю о boost::shared_ptr
, std::unique_ptr
(C ++ 11) и boost::ptr_(vector|list|map)
, но они не решают проблему дублирующегося указателя.
Просто, чтобы описать проблему - у меня есть функция, которая принимает выделенный из кучи указатель и сохраняет его для будущего использования:
void SomeClass::add(T* ptr)
{
_list.push_back(ptr);
}
Но если я вызову add
дважды с одним и тем же параметром ptr
- _list
будет содержать два указателя на один и тот же объект, и когда _list
будет уничтожен, произойдет многократное удаление одного и того же объекта.
Если _list
будет считать указатель, который он хранит и использует их во время удаления, тогда эта проблема будет решена, и объекты не будут удалены несколько раз.
Итак, вопрос:
Кто-нибудь знает какую-нибудь библиотеку с коллекциями (вектором, списком, по сути, картой) указателя с автоматическим удалением при уничтожении и поддержкой подсчета ссылок?
Или, может быть, я могу решить эту проблему, используя другую технику?
Обновление:
Мне нужна поддержка дублирующих указателей. Так что я не могу использовать std::set
.
Как упомянуто Kerrek SB и Grizzly - плохая идея вообще использовать необработанные указатели и предлагает использовать std::make_shared
и забыть об инстанцировании через new
. Но это ответственность клиентского кода, а не класса, который я проектирую. Даже если я поменяю add
подпись (и, конечно, _list
контейнер) на
void SomeClass::add(std::shared_ptr<T> ptr)
{
_list.push_back(ptr);
}
тогда кто-то (кто не знает о std::make_shared
) все еще может написать это:
SomeClass instance;
T* ptr = new T();
instance.add(ptr);
instance.add(ptr);
Так что это не полное решение, которое я жду, но полезно, если вы пишете один код.
Обновление 2:
В качестве альтернативного решения я нашел клонирование (используя конструктор сгенерированных копий). Я имею в виду, что я могу изменить свою add
функцию следующим образом:
template <typename R>
void SomeClass::add(const R& ref)
{
_list.push_back(new R(ref));
}
это позволит виртуальным методам (R - класс, который расширяет некоторый базовый класс (интерфейс)) вызывать и запрещать повторяющиеся указатели. Но у этого решения есть издержки для клона.