在 QSharedPointer 中管理 QAbstractItemModel 数据
Managing QAbstractItemModel data in QSharedPointers
在 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));
}
}
所以你可以看到两件事:
你从一个值创建一个 QVariant,你正在按值传递这个 QVariant,这意味着 QVariant 有自己的内存,内存管理被传递给请求数据的对象(你不能返回 QVariant 的共享指针,因为你需要实现这个特定的方法签名)
该实现独立于您用于"消息队列"列表的内存策略
如果你对列表中的数据使用共享指针,你不需要担心析构函数上列表的释放,如果你不这样做,你需要删除类析构函数中的列表。
如果你想讨论在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 的深层副本来绕过整个同步(这意味着您将复制它的内部指针,然后使其成为共享指针),但如果可能的话,我会使用同步。
- 没有找到相关文章