在 QSharedPointer 中管理 QAbstractItemModel 数据

Managing QAbstractItemModel data in QSharedPointers

本文关键字:QAbstractItemModel 数据 管理 QSharedPointer      更新时间:2023-10-16

在 c++ Qt 中,我喜欢使用 QSharedPointer 管理我的堆内存,但是是否可以/是否也应该使用它们来管理 QAbstractItemModel 中的数据?

例如,可以有一个 QStrings 列表 QList<QSharedPointer<QString> > queue .

问题是,在实现QSharedAbstractItemModel时,如QAbstractListModel,您需要处理原始指针。例如,方法索引返回一个 QModelIndex,该索引在构造函数中获取一个 void 指针,指向堆上的其中一个 QString。创建该对象后,您将使用托管和非托管堆内存。

因此,如果我将所选项目存储在指针中的某个位置,然后清除模型,则该指针的数据将被删除。

那么如何处理要放入QAbstractItemModel的堆内存对象

我使用 qt 5.1。

在内存管理方面,这取决于您的选择。

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. 该实现独立于您用于"消息队列"列表的内存策略

如果你对列表中的数据使用共享指针,你不需要担心析构函数上列表的释放,如果你不这样做,你需要删除类析构函数中的列表。

如果你想讨论在QAbstarctListModel实现中使用QSharedPointers是好的,你会得到与问题"在项目中使用共享指针时它有用吗以及权衡是什么?"相同的答案。

编辑:

关于您的评论:

您担心当使用createIndex生成QModelIndex并使用QModelIndex内部原始指针时会发生什么。

在 QT 文档中:

注意:模型索引应立即使用,然后丢弃。在调用更改模型结构或删除项的模型函数后,不应依赖索引来保持有效。如果需要随时间推移保留模型索引,请使用 QPersistentModelIndex。

QModelIndex QAbstractItemModel::createIndex ( int row, int column, void * ptr = 0 ) const [protected]

使用内部指针 ptr 为给定行和列创建模型索引。

使用 QSortFilterProxyModel 时,其索引有自己的内部指针。不建议在模型外部访问此内部指针。请改用 data() 函数。

我的理解是,QModelIndex 只是用于从模型中检索数据的临时结构。在使用数据库时,可以将其视为一个临时表的等价物:你知道你会从表中访问某些信息(不是所有信息)在程序的某个部分进行多个操作,但你不想在数据库中查询每个信息,你只是在一个查询中批量获取它们,根据您的需要使用它们,然后丢弃。

QT文档提到了一个实际的例子,说明QModelIndex可以用来访问模型外部的数据(所以你不使用model.data,而是使用QModelIndex.data),但这是一个例外,因为虽然数据以输入的顺序存在于内存中,但它们的索引发生了变化(由于排序/过滤)。

在内存管理方面,QModelIndex将弱指针保留在其中,因此,如果您删除数据,QModelIndex将指向无效位置。但是丢弃内存的int术语您不必担心,因为它不会动态分配任何东西(弱指针:))。

您需要担心的地方确实是在多线程环境中,在线程 A 中获取 QModelIndex,但在线程 A 丢弃此 QModelIndex 之前,您的线程 B 会删除模型。但是,如果遇到此问题,则会出现同步问题。

您可以通过创建 QModelIndex 的深层副本来绕过整个同步(这意味着您将复制它的内部指针,然后使其成为共享指针),但如果可能的话,我会使用同步。

相关文章:
  • 没有找到相关文章