2010-03-28 1 views
4

У меня есть набор общих указателей:Удалить из ЗППП :: набор <shared_ptr <T>> Т *

std::set<boost::shared_ptr<T>> set; 

и указатель:

T* p; 

Я хотел бы эффективно удалите элемент set, равный p, но я не могу сделать это ни с одним из элементов набора или с любым из стандартных алгоритмов, так как T* - это совсем другой тип: boost::shared_ptr<T>.

Несколько подходов я могу думать о том, являются:

  • как-то строительство нового shared_ptr из указателя, который не будет брать на себя ответственность заостренный памяти (идеальное решение, но я не могу видеть, как сделать это)
  • оберточную/повторного внедрения shared_ptr, так что я могу сделать выше
  • просто делает свой собственный бинарный поиск по множеству
+0

Почему у вас есть этот необработанный указатель T в любом случае? – dalle

+1

Почему бы и нет? Я часто встречаюсь с умными указателями в классе «Factory» и только с внешними указателями/ссылками. Внешняя сторона не должна знать, как я управляю своими объектами. –

ответ

9

Построить a shared_ptr<T> от T с null_deleter (см. boost:::shared_ptr FAQ).

struct null_deleter { 
    void operator()(void const *) const { } 
}; 

size_t remove_ptr_from_set(std::set<boost::shared_ptr<T>> &set, X* x) 
{ 
    shared_ptr<X> px(x, null_deleter()); 
    return set.erase(px); 
} 

Таким образом, типы совместимы, и вам не нужно беспокоиться о том, что ваш временный shared_ptr удаляет любой объект.

Или, как говорится в одном из комментариев, если вы можете изменить T для наследования с enable_shared_from_this, вы можете получить правильный общий ptr из своего объекта.

+0

А, спасибо! Это простое решение, которое я искал. – James

+0

+1 Дарн, собирался опубликовать это. Сначала я отклонил это из-за (неправильной) идеи о том, что делетер был частью типа 'shared_ptr'. –

+2

Существует фактически отдельный FAQ для получения 'shared_ptr' из' this' в FAQ, связанный в этом ответе. Кажется, есть шаблон класса, называемый 'enable_shared_from_this', который при унаследовании предоставляет' weak_ptr' 'this'. См. Http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/enable_shared_from_this.html. –

1

Если причина для использования набора является то, что вам нужно эффективно найти указатели типа T, тогда очевидный ответ - не сделать его набором общих указателей! Вместо этого заверните набор в класс, который управляет временем жизни указателей, содержащихся в наборе.

+0

композиция над наследством! – Eric

+0

Это похоже на большой объем работы по сравнению с другими параметрами (вот почему я не перечислил его!): _only_ time Мне нужно искать по указателю, а не shared_ptr, когда я удаляю объекты (и объекты могут сохраняться после удаления до уничтожения последнего пользователя shared_ptr), поэтому я не могу слепо связать срок жизни объектов с их содержимым в контейнере. – James

+0

@ Эрик - на самом деле. 'std :: set >' уже является композицией, а не наследованием. Нейл предлагает составить правильные вещи, а не сочинять неправильные вещи. –

1

Вы можете использовать boost::ptr_set, если вы хотите, чтобы набор имел право собственности на объекты, или boost::reference_wrapper, если вы хотите, чтобы набор сохранял ссылки на них. Если вы используете shared_ptr в одном месте в своем коде, вам придется использовать его во всех местах или подвергать риску страшные сбои (оборванные указатели, уже удаленные объекты и т. Д.). Исключением является weak_ptr, указатель, указывающий на объект, принадлежащий shared_ptr, но не имеющий права собственности.

+0

Набор является одним владельцем объектов, но другие пользователи могут сохраняться после их удаления из набора, поэтому 'boost :: ptr_set 'не подходит. По этой причине я также не могу использовать 'reference_wrapper' или' weak_ptr', так как в обоих случаях пользователи могут остаться с оборванными ссылками. – James

+0

Использование указателей также сопряжено с риском, ну, оборванных указателей. Почему вы не можете удалить объекты с помощью 'shared_ptr'? Почему вы вводите туда нормальный указатель? –

+0

Я хочу удалить изнутри функцию-член из объектов, хранящихся, поэтому где-то выше в стеке есть shared_ptr, ссылающийся на объект, но я не хочу, чтобы его передавать, когда указатель 'this' легко доступны. В основном я хочу сделать: 'removeFromSet (this)' – James

Смежные вопросы