Russian Qt Forum
Ноябрь 27, 2024, 10:27 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Как правильно удалять объекты?  (Прочитано 8428 раз)
usr00210
Гость
« : Август 31, 2010, 03:57 »

Если я создаю дочерние объекты/элементы, должен ли я явно, через delete например, удалять их, скажем в деструкторе парента?
Или же сам парент позаботится о своих детях?
Есть ли какие-то исключения, особые правила и т.п. на эту тему в Кьют?

Спасибо!
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #1 : Август 31, 2010, 06:33 »

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

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
usr00210
Гость
« Ответ #2 : Август 31, 2010, 07:10 »

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

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

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

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

ПС. фраза "указываешь ему родителя" означает MyChildWidget( this ) внутри парента? Т.е. если без this, то парент ничего знать будет о ребенки и не сможет правильно освободить ресурсы?
« Последнее редактирование: Август 31, 2010, 07:12 от usr00210 » Записан
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #3 : Август 31, 2010, 07:59 »

>>означает MyChildWidget( this )
не обязательно "этот". Родителем может быть и другой виджет, всё зависит от иерархии объектов. Если иерархия существует, т.е. аргумент "parent" не был оставлен пустым. Тогда удаление будет происходить автоматически.

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

Юра.
Alex_cs_gsp
Гость
« Ответ #4 : Август 31, 2010, 08:45 »

Пока логики не нашел, так что приходится для каждого метода, который принимает указатель на объект, лезть в справку и выискивать будет ли он его прибивать или нет.
Записан
usr00210
Гость
« Ответ #5 : Август 31, 2010, 09:53 »

>>означает MyChildWidget( this )
не обязательно "этот". Родителем может быть и другой виджет, всё зависит от иерархии объектов. Если иерархия существует, т.е. аргумент "parent" не был оставлен пустым. Тогда удаление будет происходить автоматически.

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

выделенное не понял.
Если я создаю кнопку на форме и не указываю эту форму в качестве парента, то кнопка не появится при вызове метода форма->show; т.е. парент ничего не знает о кнопке.
Записан
usr00210
Гость
« Ответ #6 : Август 31, 2010, 09:58 »

Пока логики не нашел, так что приходится для каждого метода, который принимает указатель на объект, лезть в справку и выискивать будет ли он его прибивать или нет.

приведите пожалуйста два примера в которых происходит автоудаление и в которых надо это делать самому. спасибо!
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #7 : Август 31, 2010, 10:23 »

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

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

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

ArchLinux x86_64 / Win10 64 bit
Denjs
Гость
« Ответ #8 : Август 31, 2010, 10:30 »

Правда в компоновщик можно помещать виджеты не указывая родителя. Т.к. компоновщик назначит им в качестве родителя  своего родителя.
выделенное не понял.
Компоновщики - все что наследовано от QLayout.
Например QGridLayout. Когда ему дают виджет длч размещения в определенных ячейках - он назначает переданному виджету родителем тот виджет, на котором он сам "лежит".
Записан
usr00210
Гость
« Ответ #9 : Август 31, 2010, 11:47 »

понятно, спасибо!
Записан
break
Гипер активный житель
*****
Offline Offline

Сообщений: 846


Просмотр профиля
« Ответ #10 : Сентябрь 01, 2010, 01:10 »

В справке по Qt написано про автоматическую уборку мусора через QObject (одна из первых статей в ассистенте по QObject) - то есть все QObject-ы этим свойством обладают (не только виджеты).
А повторное удаление не приводит к проблеме (например если вы все же удаляете дочерний объект сами) т.к. QObject родитель работает с дочерними объектами через "умные указатели" (QPointer). И в деструкторе в момент прохода по чилдам имеет возможность проверить существует ли этот чилд и только если да - пытается его удалить...
Записан
Alex_cs_gsp
Гость
« Ответ #11 : Сентябрь 01, 2010, 14:21 »

А как знает предок что потомок был удален, если я delete вызываю для области памяти? Используется какая-то глобальная таблица?

Например,

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

delete pwgt;

Откуда лейаут знает, что виджет был удален. Я так понял тут используется какой-то другой механизм, вместо подсчета ссылок? Или банально деструктор потомка находит предка и обнуляет соответствующую ссылку у объекта предка?
 
« Последнее редактирование: Сентябрь 01, 2010, 14:23 от Alex_cs_gsp » Записан
break
Гипер активный житель
*****
Offline Offline

Сообщений: 846


Просмотр профиля
« Ответ #12 : Сентябрь 01, 2010, 14:27 »

Чем QPointer в данном случае не заработает? В исходники не смотрел только предполагаю что работает через него. Зачем чилду лезть в парент? У парента список чилдов - но не прямых "тупых указателей", а список указателей "завернутых в QPointer", которые автоматически обнуляются при удалении объекта.
Записан
BRE
Гость
« Ответ #13 : Сентябрь 01, 2010, 14:30 »

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

Чем QPointer в данном случае не заработает? В исходники не смотрел только предполагаю что работает через него. Зачем чилду лезть в парент? У парента список чилдов - но не прямых "тупых указателей", а список указателей "завернутых в QPointer", которые автоматически обнуляются при удалении объекта.
Там используется обычный QObjectList, т.е. просто QList<QObject*>
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.087 секунд. Запросов: 23.