c++ - Удаление объектов, отправленных по сигналам, Владение объектами в сигналах, Qt




signals-slots qt-signals (3)

Вы можете связать сигнал с любым количеством слотов, сколько хотите, поэтому вы должны убедиться, что ни один из этих слотов не может делать то, что вы не хотели бы, чтобы он делал с вашим объектом:

  • если вы решите передать указатель в качестве параметра, тогда вы будете работать с проблемами, которые вы описываете, управление памятью - здесь никто не сможет работать за вас, так как вам придется установить политику для работы с распределением / удалением. Некоторые идеи о том, как решить эту проблему, см. В Правилах управления памятью в мире COM .
  • если вы решили передать параметр в качестве ссылки, вам не нужно беспокоиться об управлении памятью, а только о слотах, которые изменяют ваш объект неожиданными способами. Идея состоит в том, чтобы не передавать указатели, если вам не нужно - вместо этого используйте ссылки, если можете.
  • если вы решите передать const ссылку, тогда, в зависимости от вашего типа соединения, QT передаст значение объекта для вас (см. this для некоторых деталей)
  • избегать любых проблем и передавать по значению :)

См. Также этот question для некоторых мыслей о передаче указателей в сигналах.

Здесь моя сигнальная декларация:

signals:
    void mySignal(MyClass *);

И как я это использую:

MyClass *myObject=new myClass();
emit mySignal(myObject);

Вот моя проблема: Кто отвечает за удаление myObject:

  1. Код отправителя, что делать, если он удаляется перед использованием myObject? Висячий указатель

  2. Слот, подключенный к сигналу, что если нет слота или более одного слота, который подключен к сигналу? Утечка памяти или свисающий указатель

Как Qt управляет этой ситуацией в своих встроенных сигналах? Использует ли он внутренний подсчет ссылок?

Каковы ваши лучшие практики?


Для первого вопроса используйте QPointer

На ваш второй вопрос

Если я ясно понял, даже если вы отправляете myObject , у вас все еще есть ссылка myObject в классе, где вы излучаете сигнал. Тогда как это будет утечка памяти или свисающий указатель? Вы все еще можете получить доступ к myObject из испущенного класса, не так ли?

Надеюсь ясно ..

Редактировать :

Из ваших комментариев я считаю, что вы освобождаете / удаляете объекты в слотах. Теперь я предполагаю, что ваша проблема в том, что если слот (освобождение памяти) вызывается один раз, два раза или не вызывается вообще.

Вы можете использовать QPointer для этого. Из документации Qt

Охраняемые указатели ( QPointer ) полезны всякий раз, когда вам нужно сохранить указатель на объект QObject , принадлежащий кому-то другому, и, следовательно, может быть уничтожен, пока вы все еще удерживаете ссылку на него. Вы можете безопасно проверить указатель на достоверность.

Пример из самой документации Qt,

     QPointer<QLabel> label = new QLabel;
     label->setText("&Status:");
     ...
     if (label)
         label->show();

объяснение продолжается так

Если QLabel будет удален за это время, переменная метки будет содержать 0 вместо неверного адреса, и последняя строка никогда не будет выполнена. Здесь QLabel будет вашим MyClass а метка - вашим myObject . И перед его использованием проверьте на Nullity .


Одним словом (хорошо, имя функции) - deleteLater () :) У всех объектов QObject есть. Он пометит объект для удаления, и это произойдет при следующем обновлении цикла событий.