Мне так хочется разглагольствовать по слабым сторонам модели памяти Qt, где многие API все еще принимают необработанные указатели, ожидая, что клиент выделит их, в то время как QObject, принявший указатель, удалит его.
Ответ на ваш вопрос: неопределенное поведение .shared_ptr
не имеет механизма, позволяющего определить, был ли удален указатель чем-либо, кроме самого shared_ptr, поэтому обычно он пытается освободить указатель во второй раз (вызывая delete для висящего указателя).Если вы хотите использовать shared_ptr, вы должны придерживаться shared_ptr в качестве единственного менеджера памяти.Это верно даже для собственной QSharedPointer
.
в Qt. То, что я обычно делал, чтобы попытаться сделать мой код достаточно безопасным для исключений при использовании чего-то вроде Qt, заключалось в использовании устаревшей auto_ptr
(unique_ptr
заменяетэто намного безопаснее, если у вас есть C ++ 11).Это единственное место, где я когда-либо испытывал желание использовать auto_ptr
, так как он предоставляет метод release
.
unique_ptr<QListWidget> widget(new QListWidget(...));
// do stuff with the widget to set it up for your GUI
some_layout.addWidget(widget.release()); // <-- release ownership so that
// the layout now becomes responsible
// for memory management
// ^^ auto_ptr works above if we don't have C++11
Если вам нужно сохранить постоянный указатель на ваш объект после того, как он уже используетсяУправляемая памятью Qt (например: указатель на ваш виджет после того, как вы вставили его в макет), просто используйте обычный указатель.На самом деле не намного лучше, что вы можете сделать, поскольку Qt теперь является диспетчером памяти для этого объекта.
Однако вы можете определить, когда объект уничтожен (и, следовательно, когда указатель недействителен), с помощью сигнала QObject::destroyed
.
Если вы хотите стать действительно сложным, вы можете создать общий тип указателя, который хранит только подклассы QObject.Поскольку QObject выдает сигнал уничтожения, этот вид интеллектуального указателя может обнаруживать, когда QObject уничтожается с помощью сигнала уничтожения, и избегать попытки удаления объекта во второй раз.Тем не менее, это может вызывать беспокойство, полагаясь на этот сигнал в многопоточном коде, и если вы реализуете общий указатель, это может стать довольно тяжелым бременем для атомного подсчета ссылок, захвата функции удаления на месте, где создан указатель (чтобы избежать модуляграницы новые / удалить несоответствия) и т. д.