在 QSharedPointers 中管理 QAbstractItemModel 数据
Managing QAbstractItemModel data in QSharedPointers
在 c++ Qt 中,我喜欢用 QSharedPointers, but can/should one also use them for managing data in a QAbstractItemModel?
管理我的堆内存
例如,可以有一个 QString 列表 QList<QSharedPointer<QString> > queue
。
问题是,在实现 QSharedAbstractItemModel
时,如 QAbstractListModel
,您需要处理原始指针。例如,index returns a QModelIndex 方法在构造函数中采用一个 void 指针,指向堆上的那些 QString 之一。一旦您创建了该对象,您就在使用托管和非托管的堆内存。
因此,如果我将所选项目存储在某个指针中,然后清除我的模型,该指针的数据将被删除。
那么如何处理要放入 QAbstractItemModel
中的堆内存对象
我用的是qt 5.1.
在内存管理方面,由您选择。
QAbstractListModel 需要您编写 returnQVariant 的数据函数。从哪里创建 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));
}
}
所以你可以看到两件事:
你从一个值创建了一个QVariant,你通过值传递这个QVariant,这意味着QVariant有他自己的内存,内存管理被传递给请求数据的对象(你不能return QVariant 的共享指针,因为你需要实现这个特定的方法签名)
该实现独立于您用于“MessageQueue”列表的内存策略
如果您对列表中的数据使用共享指针,则无需担心析构函数中列表的重新分配,如果不需要,则需要删除 class 中的列表' es 析构函数.
如果您想讨论在 QAbstarctListModel 实现中使用 QSharedPointers 的好处,您会得到与“在项目中使用共享指针是否有用以及有什么权衡取舍?”这个问题相同的答案。 “ .
编辑:
关于您的评论:
你担心createIndex生成QModelIndex和使用QModelIndex内部原始指针会发生什么。
在 QT 文档中:
Note: Model indexes should be used immediately and then discarded. You should not rely on indexes to remain valid after calling model functions that change the structure of the model or delete items. If you need to keep a model index over time use a QPersistentModelIndex.
...
QModelIndex QAbstractItemModel::createIndex ( int row, int column, void * ptr = 0 ) const [protected]
Creates a model index for the given row and column with the internal pointer ptr.
When using a QSortFilterProxyModel, its indexes have their own internal pointer. It is not advisable to access this internal pointer outside of the model. Use the data() function instead.
我的理解是 QModelIndex 只是一个用于从模型中检索数据的临时结构。将其视为等同于使用数据库时的临时 table :您知道您将从 table 访问某些信息(不是所有信息)以进行程序特定部分的多个操作,但是你不想为每个查询数据库,你只是在一次查询中将它们作为一个批量获取,根据你的需要使用它们然后你丢弃。
QT 文档提到了一个实际示例,其中 QModelIndex 可用于访问模型外的数据(因此您使用 QModelIndex.data 而不是 model.data),但这是一个例外,因为虽然数据以相同的顺序存在于内存中,它们的索引发生了变化(由于排序/过滤)。
在内存管理方面,QModelIndex 内部保留了弱指针,所以实际上,如果删除数据,您的 QModelIndex 将指向无效位置。但是就丢弃内存而言,您不必担心,因为它不会动态分配任何东西(弱指针 :))。
您确实需要担心的是在多线程环境中,您在线程 A 中获得了一个 QModelIndex,但在线程 A 丢弃此 QModelIndex 之前,您的线程 B 删除了模型。但是,如果你有这个,你有一个同步问题。
您可以通过创建 QModelIndex 的深层副本来绕过整个同步(这意味着您将复制它的内部指针,然后将其设为共享指针),但如果可能的话我会使用同步。
在 c++ Qt 中,我喜欢用 QSharedPointers, but can/should one also use them for managing data in a QAbstractItemModel?
管理我的堆内存例如,可以有一个 QString 列表 QList<QSharedPointer<QString> > queue
。
问题是,在实现 QSharedAbstractItemModel
时,如 QAbstractListModel
,您需要处理原始指针。例如,index returns a QModelIndex 方法在构造函数中采用一个 void 指针,指向堆上的那些 QString 之一。一旦您创建了该对象,您就在使用托管和非托管的堆内存。
因此,如果我将所选项目存储在某个指针中,然后清除我的模型,该指针的数据将被删除。
那么如何处理要放入 QAbstractItemModel
我用的是qt 5.1.
在内存管理方面,由您选择。
QAbstractListModel 需要您编写 returnQVariant 的数据函数。从哪里创建 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));
}
}
所以你可以看到两件事:
你从一个值创建了一个QVariant,你通过值传递这个QVariant,这意味着QVariant有他自己的内存,内存管理被传递给请求数据的对象(你不能return QVariant 的共享指针,因为你需要实现这个特定的方法签名)
该实现独立于您用于“MessageQueue”列表的内存策略
如果您对列表中的数据使用共享指针,则无需担心析构函数中列表的重新分配,如果不需要,则需要删除 class 中的列表' es 析构函数.
如果您想讨论在 QAbstarctListModel 实现中使用 QSharedPointers 的好处,您会得到与“在项目中使用共享指针是否有用以及有什么权衡取舍?”这个问题相同的答案。 “ .
编辑:
关于您的评论:
你担心createIndex生成QModelIndex和使用QModelIndex内部原始指针会发生什么。
在 QT 文档中:
Note: Model indexes should be used immediately and then discarded. You should not rely on indexes to remain valid after calling model functions that change the structure of the model or delete items. If you need to keep a model index over time use a QPersistentModelIndex.
...
QModelIndex QAbstractItemModel::createIndex ( int row, int column, void * ptr = 0 ) const [protected]
Creates a model index for the given row and column with the internal pointer ptr.
When using a QSortFilterProxyModel, its indexes have their own internal pointer. It is not advisable to access this internal pointer outside of the model. Use the data() function instead.
我的理解是 QModelIndex 只是一个用于从模型中检索数据的临时结构。将其视为等同于使用数据库时的临时 table :您知道您将从 table 访问某些信息(不是所有信息)以进行程序特定部分的多个操作,但是你不想为每个查询数据库,你只是在一次查询中将它们作为一个批量获取,根据你的需要使用它们然后你丢弃。
QT 文档提到了一个实际示例,其中 QModelIndex 可用于访问模型外的数据(因此您使用 QModelIndex.data 而不是 model.data),但这是一个例外,因为虽然数据以相同的顺序存在于内存中,它们的索引发生了变化(由于排序/过滤)。
在内存管理方面,QModelIndex 内部保留了弱指针,所以实际上,如果删除数据,您的 QModelIndex 将指向无效位置。但是就丢弃内存而言,您不必担心,因为它不会动态分配任何东西(弱指针 :))。
您确实需要担心的是在多线程环境中,您在线程 A 中获得了一个 QModelIndex,但在线程 A 丢弃此 QModelIndex 之前,您的线程 B 删除了模型。但是,如果你有这个,你有一个同步问题。
您可以通过创建 QModelIndex 的深层副本来绕过整个同步(这意味着您将复制它的内部指针,然后将其设为共享指针),但如果可能的话我会使用同步。