Управление данными QAbstractItemModel в QSharedPointers

В c ++ Qt мне нравится управлять своей кучей памяти с помощью QSharedPointers, но можно / нужно также использовать их для управления данными в QAbstractItemModel?

Например, можно иметь список QStrings QList<QSharedPointer<QString> > queue,

Проблема в том, что при реализации QSharedAbstractItemModel, словно QAbstractListModelнужно разобраться с необработанными указателями. Например, метод индекс возвращает QModelIndex это берет пустой указатель в конструкторе, указывая на одну из тех QStrings в куче. Как только вы создаете этот объект, вы работаете с кучей памяти, управляемой и неуправляемой.

Поэтому, если я сохраню выбранный элемент где-нибудь в указателе, а затем очисту свою модель, данные для этого указателя будут удалены.

Так как же работать с объектами кучи памяти, которые вы хотите поместить в QAbstractItemModel

Я использую QT 5.1.

2

Решение

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

QAbstractListModel требует, чтобы вы написали функцию данных, которая возвращает QVariant. Где вы создаете этот вариант, на самом деле не имеет значения.

Сам QVariant — это новая структура, которая никак не влияет на ваши данные.

Возьмите этот пример:

 QVariant MyListImplementation::data(const QModelIndex& index, int role) const
{
// QSharedPointer<QList<QString>> sharedMessageQueue
// QList<QString>* pMessageQueue
if (useSharedPointers)
{
return QVariant::fromValue(sharedMessageQueue->at(index.row()));
} else {
return QVariant::fromValue(pMessageQueue->at(index.row));
}
}

Таким образом, вы можете увидеть две вещи:

  1. Вы создаете QVariant из значения и передаете этот QVariant по значению, что означает, что QVariant имеет свою собственную память, а управление памятью передается объекту, который запрашивает данные (Вы не можете вернуть общий указатель QVariant, так как вы нужно реализовать этот конкретный метод подписи)

  2. Реализация не зависит от политики памяти, которую вы используете для своего списка «MessageQueue»

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

Если вы хотите обсудить, хорошо ли использовать QSharedPointers внутри реализации QAbstarctListModel, вы получите те же ответы, что и на вопрос «Это полезно и каковы компромиссы при использовании общих указателей внутри проекта?» ,

РЕДАКТИРОВАТЬ :

По поводу вашего комментария:

Вы беспокоитесь о том, что происходит, когда createIndex используется для генерации QModelIndex и использования внутреннего необработанного указателя QModelIndex.

В документации QT:

Примечание. Модельные индексы должны использоваться немедленно, а затем отбрасываться. Не следует полагаться на то, что индексы остаются действительными после вызова функций модели, которые изменяют структуру модели или удаляют элементы. Если вам нужно сохранить модельный индекс во времени, используйте QPersistentModelIndex.

QModelIndex QAbstractItemModel :: createIndex (строка int, столбец int, void * ptr = 0) const [защищенный]

Создает модельный индекс для данной строки и столбца с внутренним указателем ptr.

При использовании QSortFilterProxyModel его индексы имеют собственный внутренний указатель. Не рекомендуется обращаться к этому внутреннему указателю за пределами модели. Вместо этого используйте функцию data ().

Насколько я понимаю, QModelIndex — это просто временная структура, используемая для извлечения данных из модели. Подумайте об этом как о эквиваленте временной таблицы при использовании базы данных: вы знаете, что получите доступ к определенной информации из таблицы (не ко всей информации) для нескольких операций в определенной части вашей программы, но вы не хотите делать запросы базу данных для каждого, вы просто получаете их в виде одного запроса, используете их в соответствии с вашими потребностями, а затем отбрасываете.

В документации QT упоминается практический пример, где QModelIndex может использоваться для доступа к данным вне модели (поэтому вместо использования model.data вы используете QModelIndex.data), но это исключение, потому что, хотя данные существуют в памяти в том же порядке был введен, их индексы изменены (из-за сортировки / фильтрации).

С точки зрения управления памятью, QModelIndex содержит слабые указатели внутри него, поэтому, если вы удалите данные, ваш QModelIndex укажет на недопустимое расположение. Но с точки зрения отказа от памяти вам не о чем беспокоиться, поскольку она не выделяет ничего динамически (слабые указатели :)).

В действительности вам нужно беспокоиться о многопоточных средах, где вы получаете QModelIndex в потоке A, но перед тем, как поток A сбросит этот QModelIndex, ваш поток B удалит модель. Однако, если у вас есть это, у вас есть проблемы с синхронизацией.

Вы можете обойти всю эту синхронизацию, создав глубокую копию QModelIndex (то есть вы скопируете его внутренний указатель, а затем сделаете его разделяемым указателем), но я бы по возможности воспользовался синхронизацией.

2

Другие решения


По вопросам рекламы [email protected]