Страницы

Поиск по вопросам

вторник, 12 февраля 2019 г.

Динамическое выделение памяти для виджета верхнего уровня

Начал изучение Qt и на определенном этапе встал вопрос с освобождением памяти, вот пример кода:
int main(int argc, char *argv[]) { QApplication a(argc, argv); Spin(); return a.exec(); }
void Spin() { QSpinBox *psb = new QSpinBox(); psb->show(); }
Верно ли так выделять память для виджета верхнего уровня в локальной функции и нигде далее не освобождать память для него?


Ответ

QObject в своём деструкторе выполняет освобождение памяти дочерних элементов. Т.е. элементов, у которых Parent установлен на уничтожаемый элемент. Например:
QObject* p = new QObject(); QObject* c1 = new QObject(p); QObject* c2 = new QObject(); c2->setParent(p);
delete p; // Вызовет уничтожение c2, c1, p
Чуть более подробнее можно почитать тут

В вашем случае при выходе из функции Spin память, адресуемая указателем psb будет утеряна, т.е. произойдёт утёчка.
Самый простой способ избежать утечки - избавиться от Spin вовсе и использовать практически канонический hello world
int main() { QApplication a(argc, argv);
QSpinBox psb; psb.show();
return a.exec(); }
Замечу, что в этом случае используется создание QSpinBox на стеке, т.е. деструктор будет вызван автоматически.
Если требуется оставить выделение памяти в куче, то нужно любым доступным образом обеспечить освобождение ресурсов psb при завершении программы.
Один из возможных способов - обернуть его в умный указатель типа QSharedPointer и вернуть наружу из функции:
QSharedPointer Spin() { QSharedPointer psb(new QSpinBox()); psb->show(); return psb; }
Код main будет выглядеть так:
int main(int argc, char *argv[]) { QApplication a(argc, argv); auto s = Spin(); return a.exec(); }
В этом случае при завершении main будет выполнено уничтожение s, который хранит в себе psb

Комментариев нет:

Отправить комментарий