2

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

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

问题是,当实现 a 时QSharedAbstractItemModelQAbstractListModel您需要处理原始指针。例如,方法index返回一个QModelIndex,它在构造函数中接受一个 void 指针,指向堆上的那些 QString 之一。一旦您创建了该对象,您就可以使用托管和非托管的堆内存。

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

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

我使用 qt 5.1。

4

1 回答 1

2

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

QAbstractListModel 需要您编写返回 QVariant 的数据函数。从哪里创建 Variant 并不重要。

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

如果您对列表中的数据使用共享指针,则无需担心 destructor 上列表的释放,如果不需要,则需要删除类的析构函数中的列表。

如果您想讨论在 QAbstarctListModel 实现中使用 QSharedPointers 是否很好,您将得到与“在项目中使用共享指针是否有用以及有哪些权衡?”的问题相同的答案。.

编辑 :

关于您的评论:

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

在 QT 文档中:

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

...

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

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

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

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

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

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

您确实需要担心的是在多线程环境中,您在线程 A 中获得了 QModelIndex ,但在线程 A 丢弃此 QModelIndex 之前,您的线程 B 删除了模型。但是,如果你有这个,你就有一个同步问题。

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

于 2015-01-21T10:25:44.477 回答