LINUX.ORG.RU

[c++] тупой вопрос про смартпойнтеры в коллекциях

 


0

0

Хочу написать коллекцию из указателей на объекты, но такую, чтобы:

а) все элементы коллекции уничтожались при уничтожении объекта класса, в котором она хранится;

б) должна быть возможность замены одного элемента коллекции другим без уничтожения старого объекта (по этой причине не подходит, к примеру, std::vector<boost::shared_ptr<ObjType> > -- у shared_ptr нет метода release(); а оборачивать объекты типа ObjType в shared_ptr везде, где они используются, у меня нет возможности);

в) в качестве коллекции выступает не обычный сишный массив (в таком случае все было бы просто -- в бусте есть соответствующие классы), а произвольная STL-евская (или другая) коллекция.

В голову приходит только что-то вроде std::vector<boost::shared_ptr<std::auto_ptr<ObjType> > >. Нет ли решения поизящнее?

★★

> в качестве коллекции выступает не обычный сишный массив, а __произвольная__ STL-евская (или другая) коллекция.

Ммм... и как это можно сделать в С++? Че-то мне кажется что нельзя.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

Почему нельзя? Пример с boost::shared_ptr<std::auto_ptr<ObjType> > показывает, что можно. Правда, оверхед немного смущает:)

V_L_A_D ★★
() автор топика
Ответ на: комментарий от gpg

блин:)

release() просто забывает о существовании старого объекта

reset() его уничтожает перед тем, как принять на хранение новый объект

Так вот -- при подмене объекта мне уничтожать ничего не нужно. Если объект один, то прекрасно подходит обычный std::auto_ptr. Если же нужно положить в коллекцию, то auto_ptr лажает, и мне необходимо искать другие способы хранения данных. Например, Boost.PointerContainer.

V_L_A_D ★★
() автор топика
Ответ на: комментарий от V_L_A_D

Хорошо, угадываю: проблема уничтожения при подмене добавлена в описание шутки ради и не несёт никакой смысловой нагрузки.
Т.е. тебе просто нужен эстээльконтейнеросовместимый смартпойнтер с возможностью отказа от владения?
В этом случае имеет смысл подумать о самостоятельной реализации такой экзотики.
Или даже поискать другое решение задачи.

gpg
()

Где-то читал про такой трюк:

template<class Container> OwningContainer : public Container {
  // сам добавляешь конструкторы, они просто вызывают
  // соответствующие конструкторы из Container
  
  ~OwningContainer {
    for(typename Container::iterator i = begin(), e = end(); i!=e; i++)
      delete *i;
  }
};

В качестве типа используешь нужный тебе контейнер,
любой который поддерживает begin/end и хранит указатели.

Например:

OwningContainer< std::map<MyClass *> > myMap;

... и пользуемся как обычным std::map. Когда map умрет,
он вызовет delete для всех элементов в нем.

Вроде бы делает то что нужно. Одна проблема - конструкторы
 надо переопределять, но это мелочи.

А "космос" на shared_ptr не переводи - если везде хватало указателей,
значит shared_ptr не нужен. Как раз сейчас занимаюсь прямо обратным 
процессом - вычищаю shared_ptr отовсюду, где им нагажено. Код 
становится проще и ясней.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.