Russian Qt Forum

Qt => Общие вопросы => Тема начата: usr00210 от Август 31, 2010, 03:57



Название: Как правильно удалять объекты?
Отправлено: usr00210 от Август 31, 2010, 03:57
Если я создаю дочерние объекты/элементы, должен ли я явно, через delete например, удалять их, скажем в деструкторе парента?
Или же сам парент позаботится о своих детях?
Есть ли какие-то исключения, особые правила и т.п. на эту тему в Кьют?

Спасибо!


Название: Re: Как правильно удалять объекты?
Отправлено: Пантер от Август 31, 2010, 06:33
Если при создании виджета ты указываешь ему родителя, то родитель после смерти прибьет его. Вручную это можно не делать.


Название: Re: Как правильно удалять объекты?
Отправлено: usr00210 от Август 31, 2010, 07:10
Если при создании виджета ты указываешь ему родителя, то родитель после смерти прибьет его. Вручную это можно не делать.

т.е. именно можно? и даже если я буду добросовестно удалять все созданные динамические объекты, это не приведет к беде?
И такие вложенные конструкции типа:

QApplication <- *MainWindow <- *VLayout <- { *Button1, *Button2, ... }

будут корректно обрабатываться с освобождением всех занятых ресурсов?

ПС. фраза "указываешь ему родителя" означает MyChildWidget( this ) внутри парента? Т.е. если без this, то парент ничего знать будет о ребенки и не сможет правильно освободить ресурсы?


Название: Re: Как правильно удалять объекты?
Отправлено: lit-uriy от Август 31, 2010, 07:59
>>означает MyChildWidget( this )
не обязательно "этот". Родителем может быть и другой виджет, всё зависит от иерархии объектов. Если иерархия существует, т.е. аргумент "parent" не был оставлен пустым. Тогда удаление будет происходить автоматически.

Правда в компоновщик можно помещать виджеты не указывая родителя. Т.к. компоновщик назначит им в качестве родителя  своего родителя.


Название: Re: Как правильно удалять объекты?
Отправлено: Alex_cs_gsp от Август 31, 2010, 08:45
Пока логики не нашел, так что приходится для каждого метода, который принимает указатель на объект, лезть в справку и выискивать будет ли он его прибивать или нет.


Название: Re: Как правильно удалять объекты?
Отправлено: usr00210 от Август 31, 2010, 09:53
>>означает MyChildWidget( this )
не обязательно "этот". Родителем может быть и другой виджет, всё зависит от иерархии объектов. Если иерархия существует, т.е. аргумент "parent" не был оставлен пустым. Тогда удаление будет происходить автоматически.

Правда в компоновщик можно помещать виджеты не указывая родителя. Т.к. компоновщик назначит им в качестве родителя  своего родителя.

выделенное не понял.
Если я создаю кнопку на форме и не указываю эту форму в качестве парента, то кнопка не появится при вызове метода форма->show; т.е. парент ничего не знает о кнопке.


Название: Re: Как правильно удалять объекты?
Отправлено: usr00210 от Август 31, 2010, 09:58
Пока логики не нашел, так что приходится для каждого метода, который принимает указатель на объект, лезть в справку и выискивать будет ли он его прибивать или нет.

приведите пожалуйста два примера в которых происходит автоудаление и в которых надо это делать самому. спасибо!


Название: Re: Как правильно удалять объекты?
Отправлено: kuzulis от Август 31, 2010, 10:23
Цитировать
выделенное не понял.
Если я создаю кнопку на форме и не указываю эту форму в качестве парента, то кнопка не появится при вызове метода форма->show; т.е. парент ничего не знает о кнопке.

Ну типа да. Только это
Цитировать
Если я создаю кнопку на форме
некорректно в данном случае потому что раз вы не указываете родителя то => кнопка не будет принадлежать этой форме!
Для того чтобы она показалась необходимо вызвать где-то в коде:
Код:
...
button->show();
...
при этом кнопка появится отдельным виджетом вне формы. И в этом случае нужно при закрытии приложения (или других причинах) ее принудительно закрывать и убивать.

Под компоновщиком тут Юрий имел ввиду Layout. При добавлении в Layout кнопки созданной без родителя автоматически Layout ей присвоит своего родителя!
т.е. (псевдокод):
Код:
...
QPushButton *btn = new QPushButton(); //тут кнопка без родителя
layout.addWidget(btn); //теперь кнопка имеет родителя и отобразится в layout
...


Название: Re: Как правильно удалять объекты?
Отправлено: Denjs от Август 31, 2010, 10:30
Правда в компоновщик можно помещать виджеты не указывая родителя. Т.к. компоновщик назначит им в качестве родителя  своего родителя.
выделенное не понял.
Компоновщики - все что наследовано от QLayout.
Например QGridLayout. Когда ему дают виджет длч размещения в определенных ячейках - он назначает переданному виджету родителем тот виджет, на котором он сам "лежит".


Название: Re: Как правильно удалять объекты?
Отправлено: usr00210 от Август 31, 2010, 11:47
понятно, спасибо!


Название: Re: Как правильно удалять объекты?
Отправлено: break от Сентябрь 01, 2010, 01:10
В справке по Qt написано про автоматическую уборку мусора через QObject (одна из первых статей в ассистенте по QObject) - то есть все QObject-ы этим свойством обладают (не только виджеты).
А повторное удаление не приводит к проблеме (например если вы все же удаляете дочерний объект сами) т.к. QObject родитель работает с дочерними объектами через "умные указатели" (QPointer). И в деструкторе в момент прохода по чилдам имеет возможность проверить существует ли этот чилд и только если да - пытается его удалить...


Название: Re: Как правильно удалять объекты?
Отправлено: Alex_cs_gsp от Сентябрь 01, 2010, 14:21
А как знает предок что потомок был удален, если я delete вызываю для области памяти? Используется какая-то глобальная таблица?

Например,

QWidget *pwgt = new QWidget();
pVLayout->addWidget(pwgt);

delete pwgt;

Откуда лейаут знает, что виджет был удален. Я так понял тут используется какой-то другой механизм, вместо подсчета ссылок? Или банально деструктор потомка находит предка и обнуляет соответствующую ссылку у объекта предка?
 


Название: Re: Как правильно удалять объекты?
Отправлено: break от Сентябрь 01, 2010, 14:27
Чем QPointer в данном случае не заработает? В исходники не смотрел только предполагаю что работает через него. Зачем чилду лезть в парент? У парента список чилдов - но не прямых "тупых указателей", а список указателей "завернутых в QPointer", которые автоматически обнуляются при удалении объекта.


Название: Re: Как правильно удалять объекты?
Отправлено: BRE от Сентябрь 01, 2010, 14:30
Откуда лейаут знает, что виджет был удален. Я так понял тут используется какой-то другой механизм, вместо подсчета ссылок?
Другой.
В конструкторе QObject (если parent != 0) указатель на конструируемый объект добавляется в специальный список parent-объекта.
При разрушении объекта в деструкторе он себя вычеркивает из списка parent-объекта.
А при разрушении самого parent-объекта в его деструкторе будут удалены все объекты содержащиеся в этом списке.


Название: Re: Как правильно удалять объекты?
Отправлено: BRE от Сентябрь 01, 2010, 14:49
Чем QPointer в данном случае не заработает? В исходники не смотрел только предполагаю что работает через него. Зачем чилду лезть в парент? У парента список чилдов - но не прямых "тупых указателей", а список указателей "завернутых в QPointer", которые автоматически обнуляются при удалении объекта.
Там используется обычный QObjectList, т.е. просто QList<QObject*>