Russian Qt Forum

Qt => Общие вопросы => Тема начата: kamil от Май 03, 2015, 13:12



Название: Вопрос про удаление QObject находящегося в иерархии
Отправлено: kamil от Май 03, 2015, 13:12
В программе возникла проблема, и я уверен, что многие с ней сталкивались.

Есть класс Plot отвечающий за отрисовку одного графика. Среди членов класса - указатели на QWidget (имя графика, цвет, и т. п.). Эти QWidget должны удаляться в двух местах:
- автоматически при выходе из программы, так как они в иерархии QObject являются потомками QMainWindow
- в ручную, когда удаляется сам экземпляр класса Plot, например когда нужно загрузить новые графики из другого файла, а старые удалить.

Если в деструкторе Plot написать:
Код:
delete pointerToWidget;
То при ручном удалении все сработает, но появится проблема при автоматическом удалении - к моменту вызова ~Plot pointerToWidget будет уже удалён, и на delete pointerToWidget; программа выпадет.
Если вместо ручного удаления просто скрывать pointerToWidget, чтобы он во время выхода сам удалился - по мере открывания файлов объекты будут скапливаться, забивая память.

Как обычно поступают в такой ситуации?


Название: Re: Вопрос про удаление QObject находящегося в иерархии
Отправлено: Bepec от Май 03, 2015, 13:29
Вы сами контролируйте состояние.
Сделайте обнуление указателя и добавьте проверку при его удалении.

Код:
if (pointerToWidget)
{
    delete pointerToWidget;
    pointerToWidget = NULL; 
}

И да, не забудьте обнулить указатель в конструкторе, а то креш словите :)


Название: Re: Вопрос про удаление QObject находящегося в иерархии
Отправлено: Old от Май 03, 2015, 13:35
Не нужна эта бесполезная проверка на 0, delete сам прекрасно это проверяет.


Название: Re: Вопрос про удаление QObject находящегося в иерархии
Отправлено: Igors от Май 03, 2015, 13:49
Как обычно поступают в такой ситуации?
Используют QPointer


Название: Re: Вопрос про удаление QObject находящегося в иерархии
Отправлено: kamil от Май 03, 2015, 17:18
Bepec, спасибо, убрал виджеты из иерархии и удаляю вручную - всё нормально.
Old, да, проверка не нужна, delete нормально есть NULL
Igors, тут вроде как и без QPointer можно обойтись - практически как и в любой другой ситуации...

Update:
Bepec, ничего не нормально. При попытке убрать виджет из иерархии (setParent(NULL)), все виджеты оказываются в отдельных окнах (странно, я думал иерархия QObject и иерархия в ui это разные вещи). Как ещё можно самому контролировать время жизни виджетов?


Название: Re: Вопрос про удаление QObject находящегося в иерархии
Отправлено: Old от Май 03, 2015, 19:28
Проверьте ещё раз, если вы виджет удаляете руками, например, в деструктор, то он автоматически вычеркивается из списка своего parent и не будет удаляться автоматически, при разрушении parent.


Название: Re: Вопрос про удаление QObject находящегося в иерархии
Отправлено: lit-uriy от Май 03, 2015, 20:04
Наследников QObject нужно удалять через их метод deleteLater()


Название: Re: Вопрос про удаление QObject находящегося в иерархии
Отправлено: Bepec от Май 03, 2015, 20:58
Нуууу, тут непонятно что у вас творится.

Тут надо выбрать один подход - или вы держитесь за систему Qt, или вы сами управляете объектами.

PS выход подсказывает lit-uriy :)


Название: Re: Вопрос про удаление QObject находящегося в иерархии
Отправлено: kamil от Май 03, 2015, 23:23
Bepec, как мне вручную контролировать время жизни объектов, которые являются частью иерархии QMainWindow?

lit-uriy, deleteLater() я использовать не могу - я уже говорил что к тому моменту как вызывается деструктор класса Plot, объект может быть удалён уже самим qt. Я не знаю как можно проверить удалён объект или нет, не используя QPointer.

Old, вы правы, если я удалил объект первым, то через иерархию QMainWindow он не станет удаляться. А если первым удалит сам Qt?

Попробую объяснить ситуацию ещё раз. Деструкор некоторого объекта вызывается в двух случаях:
 - во время работы программы. В этом случае нужно удалить некоторый QWidget вручную.
 - когда закрывается программа. В этом случае QWidget уже может быть удалён самим Qt как потомок в иерархии QMainWindow.

Действительно, как говорил Верес, нужно, например, управлять временем жизнью QObject самостоятельно. Как это сделать я не знаю.
Либо же оставить право Qt удалять объекты, но проверять, не удалён ли уже объект, прежде чем вызывать delete. Как это сделать я тоже не знаю.
В голову пока приходит только QPointer.


Название: Re: Вопрос про удаление QObject находящегося в иерархии
Отправлено: Old от Май 04, 2015, 02:07
Дочернии объекты удаляются только при удалении родительского объекта. Т.е. в вашем случае, при удалении главного окно. Как правило это происходит в функции main при завершении программы. До этого момента, Qt не сможет ничего удалить, поэтому смело удаляйте нужные объекты руками, там где это нужно.


Название: Re: Вопрос про удаление QObject находящегося в иерархии
Отправлено: Igors от Май 04, 2015, 09:01
Igors, тут вроде как и без QPointer можно обойтись - практически как и в любой другой ситуации...
Можно, но зачем? Не вижу какие минусы имеет это решение, тем более оно штатное. Может что-то "оптимизировать" собрались?  :)


Название: Re: Вопрос про удаление QObject находящегося в иерархии
Отправлено: Bepec от Май 04, 2015, 11:50
to Old:
Проверка на NULL нужна не для delete, а для пользователя. Он вполне бы не инициализировал нуллом в конструкторе и поймал непонятный креш. Лишь дополнительный контроль за собой, хотя самоуверенные и люди с опытом, могут не пользоваться :D


Название: Re: Вопрос про удаление QObject находящегося в иерархии
Отправлено: Old от Май 04, 2015, 12:22
to Old:
Проверка на NULL нужна не для delete, а для пользователя. Он вполне бы не инициализировал нуллом в конструкторе и поймал непонятный креш. Лишь дополнительный контроль за собой, хотя самоуверенные и люди с опытом, могут не пользоваться :D
Если пользователь не инициализирует указатель в конструкторе, он словит тотже краш. Эта проверка ему ничем не поможет.


Название: Re: Вопрос про удаление QObject находящегося в иерархии
Отправлено: Bepec от Май 04, 2015, 21:00
Эта проверка поможет тем, что на ней проверка на Null явная и её можно пошагово разобрать.
И понять, что указатель не равен NULL, а не "что то произошло внутри delete, а вот что - хрен разбрёшь" :)

Собственно это для удобства программиста и отладки. Акцентирую - отладки, а не для написания совершенного кода :D


Название: Re: Вопрос про удаление QObject находящегося в иерархии
Отправлено: Old от Май 04, 2015, 21:08
Тогда лучше так:
Код
C++ (Qt)
if( ptr )
{
   if(ptr )
   {
       delete ptr;
       ptr = 0;
   }
   ptr = 0;
}
 


Название: Re: Вопрос про удаление QObject находящегося в иерархии
Отправлено: Bepec от Май 04, 2015, 21:33
Не возводите предъосторожность в степень идиотизма :)


Название: Re: Вопрос про удаление QObject находящегося в иерархии
Отправлено: Old от Май 04, 2015, 21:35
Не возводите предъосторожность в степень идиотизма :)
Это не более идиотизм, чем ваша проверка.


Название: Re: Вопрос про удаление QObject находящегося в иерархии
Отправлено: Bepec от Май 04, 2015, 21:40
Ну давайте, расскажите мне, в чем ошибка в моём случае. Просто дополнительное условие, вынесенное в зону контроля программиста, а не стандартной библиотеки.

PS расскажите расскажите как это плохо, жрёт кучу тактов процессора на обработку. Давайте, откройте правду :)

PPS и расскажите сотням новичков, которые могут отловить этот тонкий нюанс простой точкой остановки. Не все с рождения и начала программирования знают о тонкостях :D


Название: Re: Вопрос про удаление QObject находящегося в иерархии
Отправлено: Old от Май 04, 2015, 21:49
Это не нужно.
Вам это не поможет, а новички после этого и так задумаются о ненужности такой проверки.


Название: Re: Вопрос про удаление QObject находящегося в иерархии
Отправлено: Bepec от Май 04, 2015, 21:54
Вы не путайте код профессиональный и код для работы.

Вообще профессиональный код выглядит как будто алфавит взбесился, никаких пояснений, многострочные формулы и отсутствие комментариев. Но с ним работать в дальнейшем невозможно. А в данном случае как раз идёт проверка на неочевидную ошибку, которую можно отладить за 5 минут имея малейшее представление об указателях. А не бежать с криками на форум - почему я делал программу по коду программы Old и у меня на delete ошибка?

PS тьфу тьфу тьфу, не буду спорить. Каждый решает для себя. Хоть дефайнте delete как _d :)


Название: Re: Вопрос про удаление QObject находящегося в иерархии
Отправлено: Old от Май 04, 2015, 21:58
Последний раз, попробуйте понять: эта проверка ничего не дает и не от чего не защищает. Она полностью бесколезна в любом коде.
Поток сознания про профкод и код для работы, даже не знаю как прокомментировать. :)


Название: Re: Вопрос про удаление QObject находящегося в иерархии
Отправлено: Bepec от Май 04, 2015, 23:47
А я не буду спорить) Читать и понять мой комментарий вы не пробовали, так что приятного вам времени дня :D

PS лучше б вместо разведения споров и насмешек написали коротко и просто "этот код кажется МНЕ избыточным" :)


Название: Re: Вопрос про удаление QObject находящегося в иерархии
Отправлено: Old от Май 05, 2015, 06:57
А я не буду спорить) Читать и понять мой комментарий вы не пробовали, так что приятного вам времени дня :D

PS лучше б вместо разведения споров и насмешек написали коротко и просто "этот код кажется МНЕ избыточным" :)
Я это написал в первом своем посте этой темы. :)