Название: Правильное удаление объектов из ++ модели ассоциированной со списком в QML Отправлено: Vladimir от Январь 23, 2020, 16:37 Доброго дня! Вопрос как правильно удалять данные из модели сделанной таким образом:
https://doc.qt.io/qt-5/qtquick-modelviewsdata-cppmodels.html пример с QObjectList-based Model. В плюсовой части есть список QList<QObject*> lstData; в который добавляется структура типа Код: class Data: public QObject добавляется lstData.append(new Data()); после этого делается context->setContextProperty("M_Data", QVariant::fromValue(lstData)); в QML части: Код: ListView интересности начинаются, когда я пытаюсь удалить данные.. чтобы удалить одну строку делаю так Код: for(int i = 0; i < lstData.count(); ++i) removeAt(); и clear() вроде как и не должны его вызывать.. ок, тогда я делаю delete lstData.takeAt(i); для удаления одной строчки и qDeleteAll(lstData); и для удаления всего списка и при этом деструктор вызывается с....(внимание!) обязательным крашем программы! :) и вот собственно как это разрулить счастье, кто отвечает за освобождение памяти.. и как это правильно сделать? Название: Re: Правильное удаление объектов из ++ модели ассоциированной со списком в QML Отправлено: kambala от Январь 23, 2020, 18:19 может дело в том, что деструктор не объявлен виртуальным?
Название: Re: Правильное удаление объектов из ++ модели ассоциированной со списком в QML Отправлено: Vladimir от Январь 23, 2020, 19:09 может дело в том, что деструктор не объявлен виртуальным? это улучшило ситуацию, т.е. теперь он крашит не стабильно каждый раз, но все же крашит через какое-то количество удалений :( Название: Re: Правильное удаление объектов из ++ модели ассоциированной со списком в QML Отправлено: Vladimir от Январь 23, 2020, 21:17 Как-то странно.. виртуальный деструктор нужен в базовом классе, для корректного удаления производных классов через указатель на базовый. Базовым классом для моего класса Data является QObject, а у него деструктор виртуальный! Поэтому вроде как все должно работать было и без добавления virtual в мой класс Data.. или что-то я не так понимаю
Название: Re: Правильное удаление объектов из ++ модели ассоциированной со списком в QML Отправлено: kambala от Январь 23, 2020, 23:57 нет, все наследники должны объявлять свой деструктор виртуальным.
раз падает при удалении объекта, значит он точно удаляется дважды. Название: Re: Правильное удаление объектов из ++ модели ассоциированной со списком в QML Отправлено: Old от Январь 24, 2020, 07:29 Нельзя просто так взять и удалить данные в модели не уведомив при этом вьюшки.
Почитайте про: void QAbstractItemModel::beginRemoveRows(const QModelIndex &parent, int first, int last) void QAbstractItemModel::endRemoveRows() Тоже касается и добавления данных в модель: void QAbstractItemModel::beginInsertRows(const QModelIndex &parent, int first, int last) void QAbstractItemModel::endInsertRows() Ну и про другие случаи не забывайте, смотрите beginXXX, endXXX. Название: Re: Правильное удаление объектов из ++ модели k Отправлено: ssoft от Январь 24, 2020, 07:37 нет, все наследники должны объявлять свой деструктор виртуальным. С чего бы это? для удаления всех строк вызываю просто lstData.clear() и это работает, НО.. я не вижу, чтобы вызывался деструктор объекта! Здесь удаляются не экземпляры объектов, а чистится массив указателей на них. Никакой деструктор вызван не будет. delete lstData.takeAt(i); для удаления одной строчки и qDeleteAll(lstData); и для удаления всего списка и при этом деструктор вызывается с....(внимание!) обязательным крашем программы! А здесь сначала удаляется один экземпляр объекта, а затем удаляются все экземпляры объектов массива, в том числе и уже удаленный. Ошибка попытки повторного удаления. Используйте qDeleteAll(lstData), а уже затем lstData.clear() и будет счастье. Ну и не забывайте про beginRemoveRows/endRemoveRows и beginResetModel/endResetModel. Название: Re: Правильное удаление объектов из ++ модели ассоциированной со списком в QML Отправлено: Vladimir от Январь 24, 2020, 09:33 Нельзя просто так взять и удалить данные в модели не уведомив при этом вьюшки. Почитайте про: void QAbstractItemModel::beginRemoveRows(const QModelIndex &parent, int first, int last) void QAbstractItemModel::endRemoveRows() Тоже касается и добавления данных в модель: void QAbstractItemModel::beginInsertRows(const QModelIndex &parent, int first, int last) void QAbstractItemModel::endInsertRows() Ну и про другие случаи не забывайте, смотрите beginXXX, endXXX. про эти методы я знаю, но где их взять если я не наследуюсь от QAbstractItemModel? по ссылке из доки, которую я привел в первом сообщении я использую QObjectList-based Model, основанную просто на QList<QObject*>. если есть такой способ, то должен быть и корректный способо удаления без begin/end методов. Название: Re: Правильное удаление объектов из ++ модели ассоциированной со списком в QML Отправлено: Old от Январь 24, 2020, 09:38 Тогда попробуйте вначале установить новый новый список, в котором уже нет удаленных строк и только после этого удалить сами объекте.
Название: Re: Правильное удаление объектов из ++ модели k Отправлено: Vladimir от Январь 24, 2020, 09:39 Цитировать Используйте qDeleteAll(lstData), а уже затем lstData.clear() и будет счастье. Именно так и делаю, но счастье не приходит, когда я писал про "delete lstData.takeAt(i); для удаления одной строчки и qDeleteAll(lstData); для удаления всего" - это разные функции удаления. когда я удаляю все я делаю сначала qDeleteAll(lstData), а потом lstData.clear(). и он рандомно крашит с виртуальным конструктором, a без виртульного он крашит стабильно Название: Re: Правильное удаление объектов из ++ модели ассоциированной со списком в QML Отправлено: Vladimir от Январь 24, 2020, 09:41 Тогда попробуйте вначале установить новый новый список, в котором уже нет удаленных строк и только после этого удалить сами объекте. т.е. в context->setContextProperty("M_Data", QVariant::fromValue(QList<QObject*>())); сначала установить пустой список, а потом уже чистить.. это идея, попробую Название: Re: Правильное удаление объектов из ++ модели ассоциированной со списком в QML Отправлено: Old от Январь 24, 2020, 09:45 т.е. в context->setContextProperty("M_Data", QVariant::fromValue(QList<QObject*>())); сначала установить пустой список, а потом уже чистить.. это идея, попробую Не обязательно.Перед удалением объекта из списка через removeAt, вызвать у него deleteLater, сделать removeAt и установить новый список. Название: Re: Правильное удаление объектов из ++ модели связанной со списком в QML [DONE] Отправлено: Vladimir от Январь 24, 2020, 11:05 Eeeee вроде заработало. Всем спасибо! Eще потестирую.. но выглядит вроде все логично! Финальный вариант такой:
удаление одного Код: for(int i = 0; i < lstData.count(); ++i) удаление всех Код: context->setContextProperty("M_Data", QVariant::fromValue(QList<QObject*>())); остался открытый теоретический вопрос нужен ли деструктор виртульным делать в дочернем классе. вроде и без него работает.. здесь его объявляют только в базовом классе http://cpp-reference.ru/articles/virtual-destructor/ Название: Re: Правильное удаление объектов из ++ модели ассоциированной со списком в QML Отправлено: Old от Январь 24, 2020, 11:10 остался открытый теоретический вопрос нужен ли деструктор виртульным делать в дочернем классе. вроде и без него работает.. Не нужно, если он в базовом уже виртуальный, то будет виртуальным и во всех потомках.Название: Re: Правильное удаление объектов из ++ модели ассоциированной со списком в QML Отправлено: kambala от Январь 24, 2020, 11:26 нет, все наследники должны объявлять свой деструктор виртуальным. С чего бы это? Название: Re: Правильное удаление объектов из ++ модели ассоциированной со списком в QML Отправлено: Old от Январь 24, 2020, 11:54 спасибо, и правда, не нужно. почему-то запомнил, что лучше везде объявлять как виртуальный. По мне, так лучше везде и объявлять, что бы не приходилось помнить/смотреть как там в базовых классах определен деструктор. :)Название: Re: Правильное удаление объектов из ++ модели ассоциированной со списком в QML Отправлено: ViTech от Январь 24, 2020, 12:27 спасибо, и правда, не нужно. почему-то запомнил, что лучше везде объявлять как виртуальный. По мне, так лучше везде и объявлять, что бы не приходилось помнить/смотреть как там в базовых классах определен деструктор. :)Как по мне, так в дочерних классах лучше всё же override (https://en.cppreference.com/w/cpp/language/override) использовать :). Название: Re: Правильное удаление объектов из ++ модели ассоциированной со списком в QML Отправлено: Old от Январь 24, 2020, 13:07 спасибо, и правда, не нужно. почему-то запомнил, что лучше везде объявлять как виртуальный. По мне, так лучше везде и объявлять, что бы не приходилось помнить/смотреть как там в базовых классах определен деструктор. :)Как по мне, так в дочерних классах лучше всё же override (https://en.cppreference.com/w/cpp/language/override) использовать :). |