2015-01-21 2 views
1

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

Например, у вас может быть список QStrings QList<QSharedPointer<QString> > queue.

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

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

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

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

+0

Halfgaar, это не отвечает на ваш вопрос, но почему бы не просто «QList '? Qt использует [implicit sharing] (http://doc.qt.io/qt-5/implicit-sharing.html), поэтому он позаботится об обмене данными для вас –

+0

Я знаю о неявном совместном использовании. Это потому, что я имею дело со списками моих собственных объектов, и мне нужно сохранить сигналы и слот-соединения. – Halfgaar

ответ

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»

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

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

EDIT:

Что касается Вашего комментария:

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

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

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

...

QModelIndex QAbstractItemModel :: CreateIndex (интермедиат строка, столбец INT, аннулируются * PTR = 0) Const [защита]

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

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

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

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

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

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

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

+0

Мой вопрос больше в строке 'QList > queue' vs' QList queue'. И метод данных не является проблемой. Я больше беспокоюсь о создании 'QModelIndex' из' queue.at', а затем обходного необработанного указателя. – Halfgaar

Смежные вопросы