Как C++ / QT - работы Выделения памяти?

Я недавно начал исследовать QT для меня, и имейте следующий вопрос:

Предположим, что у меня есть некоторые QTreeWidget* widget. В некоторый момент я хочу добавить некоторые объекты к нему, и это сделано через следующий вызов:

QList<QTreeWidgetItem*> items;

// Prepare the items
QTreeWidgetItem* item1 = new QTreeWidgetItem(...);
QTreeWidgetItem* item2 = new QTreeWidgetItem(...);
items.append(item1);
items.append(item2);

widget->addTopLevelItems(items);

До сих пор это смотрит хорошо, но я на самом деле не понимаю, кто должен управлять временем жизни объектов. Я должен объяснить это с примером:

Скажем, другой вызовы функции widget->clear();. Я не знаю то, что происходит под этим вызовом, но я действительно думаю та память, выделенная для item1 и item2 не становится склонным здесь, потому что их ownage не был на самом деле передан. И, удар, у нас есть утечка памяти.

Вопрос следующий - делает Qt что-то имеет для предложения для этого вида ситуации? Я мог использовать boost::shared_ptr или любой другой интеллектуальный указатель и запись что-то как

shared_ptr<QTreeWidgetItem> ptr(new QTreeWidgetItem(...));
items.append(ptr.get());

но я не знаю, попытался ли сам QT сделать явным delete запросы к моим указателям (который имел бы катастрофические последствия, так как я заявляю им как shared_ptr- управляемый).

Как Вы решили бы эту проблему? Возможно, все очевидно, и я пропускаю что-то действительно простое?

9
задан secretgenes 9 August 2017 в 08:18
поделиться

3 ответа

Беглый взгляд на qtreewidget.cpp показывает следующее:

void QTreeWidget::clear()
{
   Q_D(QTreeWidget);
   selectionModel()->clear();
   d->treeModel()->clear();
}

void QTreeModel::clear()
{
   SkipSorting skipSorting(this);
   for (int i = 0; i < rootItem->childCount(); ++i) {
       QTreeWidgetItem *item = rootItem->children.at(i);
       item->par = 0;
       item->view = 0;
       delete item;     //   <<----- Aha!
   }
   rootItem->children.clear();
   sortPendingTimer.stop();
   reset();
}

Похоже, что ваш вызов widget-> addTopLevelItems () действительно заставляет QTreeWidget стать владельцем QTreeWidgetItems. Таким образом, вы не должны удалять их самостоятельно или хранить их в shared_ptr, иначе вы столкнетесь с проблемой двойного удаления.

7
ответ дан 2 November 2019 в 23:59
поделиться

В Qt есть собственные интеллектуальные указатели, посмотрите http://doc.qt.io/archives/4.6/qsharedpointer.html . Обычно, однако, рекомендуется использовать стандартную иерархию владения Qt, когда это возможно. Эта концепция описана здесь: http://doc.qt.io/archives/4.6/objecttrees.html

Для вашего конкретного примера это означает, что вы должны передавать указатель на контейнер (т.е. QTreeWidget) в конструктор дочерних объектов. Каждый конструктор подкласса QWidget принимает указатель на QWidget для этой цели. Когда вы передаете указатель на дочерний объект в контейнер, контейнер берет на себя ответственность за очистку дочерних объектов. Вот как вам нужно изменить ваш пример:

QTreeWidgetItem* item1 = new QTreeWidgetItem(..., widget);
QTreeWidgetItem* item2 = new QTreeWidgetItem(..., widget);

(я не знаю, что такое ... в вашем примере, но для управления памятью Qt важен последний аргумент).

Ваш пример использования умного указателя

shared_ptr<QTreeWidgetItem> ptr(new QTreeWidgetItem(...));
items.append(ptr.get());

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

4
ответ дан 2 November 2019 в 23:59
поделиться

Многие экземпляры классов Qt могут быть построены с родительским QObject*. Этот родитель контролирует время жизни построенного дочернего объекта. Посмотрите, может ли QTreeWidgetItem быть связан с родительским виджетом, похоже, что да, читая документацию Qt:

Элементы обычно конструируются с родителем, который является либо QTreeWidget (для элементов верхнего уровня) или QTreeWidgetItem (для элементов на более низких уровнях дерева).

1
ответ дан 2 November 2019 в 23:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: