QSharedPointer и QObject::deleteLater

У меня есть ситуация, когда управляемый объект QSharedPointer сигнализирует о том, что он выполнил свою задачу и вскоре готов к удалению (после выполнения функция покинула функцию, испускающую мой сигнал readyForDeletion). При работе с обычными указателями я бы просто вызывал QObject::deleteLater для объекта, однако это невозможно с экземпляром, управляемым QSharedPointer. Мой обходной путь следующий:

template<typename T>
class QSharedPointerContainer : public QObject
{
   QSharedPointer<T> m_pSharedObj;

public:

   QSharedPointerContainer(QSharedPointer<T> pSharedObj)
      : m_pSharedObj(pSharedObj)
   {} // ==> ctor

}; // ==> QSharedPointerContainer

template<typename T>
void deleteSharedPointerLater(QSharedPointer<T> pSharedObj)
{
   (new QSharedPointerContainer<T>(pSharedObj))->deleteLater();
} // ==> deleteSharedPointerLater

Это работает хорошо, однако при использовании этого метода возникает много накладных расходов (выделение нового QObject и т. д.). Есть ли лучшее решение для таких ситуаций?


person athre0z    schedule 27.09.2012    source источник
comment
Итак, у вас есть объект, управляемый совместным владением (существует несколько объектов, заявляющих о праве собственности), но в то же время он управляет своим собственным временем жизни (благодаря сигналу readyForDeletion)? Мне кажется, у вас действительно запутанная ситуация с собственностью. Вместо того, чтобы искать обходные пути, попробуйте выяснить, кто действительно отвечает за объект и, следовательно, кто должен его удалить.   -  person Sebastian Redl    schedule 27.09.2012
comment
Я должен согласиться с @Sabastian. Я собирался опубликовать аналогичный комментарий, когда он пришел. Если ваш объект отслеживает, когда его безопасно удалить, просто используйте простой старый указатель и обработайте сигнал readyForDeletion для любого класса, создающего объект в первую очередь.   -  person Dave Mateer    schedule 27.09.2012
comment
Спасибо за ваши Коментарии. В моей реальной программе все намного сложнее, однако, взглянув на абстрактную проблему, становится ясно, что использование QSharedPointer в этом контексте вообще не лучшая идея.   -  person athre0z    schedule 27.09.2012


Ответы (2)


Вы можете использовать QSharedPointer конструктор с Deleter :

Параметр удаления указывает пользовательское средство удаления для этого объекта. Пользовательское средство удаления вызывается вместо оператора delete(), когда счетчик сильных ссылок падает до 0. Это полезно, например, для вызова deleteLater() для QObject вместо этого:

 QSharedPointer<MyObject> obj =
         QSharedPointer<MyObject>(new MyObject, &QObject::deleteLater);
person pnezis    schedule 27.09.2012
comment
О, как я мог пропустить это. Это, очевидно, лучшее решение описанной проблемы, однако я решил придерживаться решения, представленного в комментариях к основному вопросу, поскольку оно имеет больше смысла в моей особой ситуации. - person athre0z; 27.09.2012

Альтернативой является использование QPointer вместо QSharedPointer со ссылкой на документацию:

Класс QPointer — это класс-шаблон, предоставляющий защищенные указатели на QObject.

Защищенный указатель, QPointer, ведет себя как обычный указатель C++ T *, за исключением того, что он автоматически устанавливается в 0, когда объект, на который указывает ссылка, уничтожается (в отличие от обычных указателей C++, которые в таких случаях становятся висячими указателями). T должен быть подклассом QObject.

person vlp    schedule 16.03.2018