Удаление объектов Отправить сигналами, владение объектами в сигналам, Qt

StackOverflow https://stackoverflow.com/questions/3183826

Вопрос

Здесь мой сигнал объявления:

signals:
    void mySignal(MyClass *);

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

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

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

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

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

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

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

Это было полезно?

Решение

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

  • Если вы решите пройти указатель в качестве параметра, вы будете работать в номерах, которые вы описываете, Memory Management Management - здесь никто не может к работе для вас, поскольку вам придется создать политику для распределения выделения / удаления. К некоторым идеям о том, как решить это, см. Правила управления памятью в Комбинированный Мир.
  • Если вы решите пройти параметр в качестве ссылки, вам не нужно беспокоиться о управлении памятью, но только о слотах, изменяющих ваш объект неожиданным способами. IDEA - не пропускать указатели, если вы не должны - вместо этого используйте ссылки, если можете.
  • Если вы решили пройти const Ссылка, затем, в зависимости от типа вашего соединения, 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.

В 1): отправитель должен заботиться. При отправке сигнала синхронно (вместо очереди) объект все еще жив, когда приемник получает его. Если приемник должен хранить его, только QPOINTER поможет, но затем MyClass должен получить из Qobject, который выглядит не так из контекста. Во всяком случае, это общая проблема срока службы, а не очень сигнал / в слоте.

Альтернативы: используйте класс значений и отправьте его через ссылку Const. Если MyClass может иметь подклассы, пропустите const qsharedpointer и

О Deletelater: Deletelater () не помогает здесь. Это сделало бы очередные соединения любого безопаснее, а для прямых соединений это не имеет значения. Один используемый, где выходит в игру, если приемник должен удалить отправителя. Тогда следует всегда использовать Deletelater (), поэтому отправитель может завершить то, что он делал, что в противном случае сбится.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top