c++ - Qt - 保持指向存储在 QList 中的内容的指针的最佳方法是什么?
问题描述
我对 Qt 和 C++ 很陌生(我一生都在研究 C# 和 Java),而且我几乎在所有地方都在阅读我不应该再使用原始指针(除了构造函数和析构函数中的指针,遵循 RAII 原则)。
我可以接受,但是有一个问题,如果没有指针,我无法轻松解决。
我会试着解释我的问题。
我正在创建一个由我创建的自定义类(MyClass)的 QList,它将充当我的应用程序的模型:
QList<MyClass> modelList;
该 QList 由工作线程根据来自网络的信息进行更新(添加、删除或更新项目)。
到目前为止,一切都很好。
现在我有另一个线程(GUI 线程),它有一个可绘制项目的 QList(MyDrawableItem)。这些项目中的每一个都有一个成员,该成员必须指向第一个 QList (modelList) 中的一个项目,如下所示:
QList<MyDrawableItem> listToDraw;
在哪里:
class MyDrawableItem
{
private:
MyObject *pointedObject;
//List of many other members related to drawing
}
因为每次 GUI 线程中的计时器到期时,我都必须根据指向的对象更新绘图相关成员。必须注意,保持指向 QList 成员的指针是安全的,如文档中所述:
注意:只要引用的项目保留在容器中,指向 QLinkedList 的迭代器和对堆分配 QList 的引用仍然有效。这不适用于迭代器和对 QVector 和非堆分配 QLists 的引用。
在内部,如果 sizeof(T) <= sizeof(void*) 并且 T 已使用 Q_DECLARE_TYPEINFO 声明为 Q_MOVABLE_TYPE 或 Q_PRIMITIVE_TYPE,则 QList 表示为 T 的数组。否则,QList 表示为 T* 数组,并且项目在堆上分配。
如果不使用指针,这怎么可能可行?或者更好的是,做这种工作的最好方法是什么?
我找到了三种可能的解决方案:
与其将pointedObject 保留为MyDrawableItem 的成员,不如将pointedObject 的索引保留在modelList 中。然后在更新中查看 QList 内部。但是如果列表中的项目被删除了怎么办?我可以发出信号,但如果更新发生在调用插槽之前?
根本不要保留任何东西作为成员,并将两个信号连接到 MyDrawableItem。一个信号是
updateDrawing(const MyObject&)
更新与绘图相关的成员,另一个信号是removeDrawing()
简单地删除对象。这样我就不必担心线程之间的同步,因为 MyDrawableItem 对象永远不会查看 QList 的内容。在这种情况下,我可能会经常使用大量信号更新项目,而我只想偶尔更新一次 GUI(500 毫秒的计时器)。只需使用指针。
发展并使用 QSharedPointers,但我从未使用过这些,我不知道这是否是最佳选择。
我认为这些解决方案都不是完美的,所以我在这里寻求您的帮助。
Qt 中的标准视图(tableview、listview、ecc.)如何处理这个问题?
我应该如何处理?
请帮帮我,我从昨天开始就在想这个,我不想弄得一团糟。
非常感谢!
解决方案
@Benjamin T 答案的补充:
如果您决定选择选项 4 并使用QSharedPointer
(或 std 变体),您实际上可以使用“弱指针”在一定程度上控制所有权。弱指针存储对对象的引用,但不拥有它。一旦最后一个“强指针”被销毁,所有弱指针都会放弃引用并将自己重置为nullptr
.
对于您的具体示例,您可以将 aQList<QSharedPointer<MyClass>>
用于模型并QWeakPointer<MyClass>
在可绘制类中使用。在绘图之前,您将在绘图函数中创建一个局部QSharedPointer<MyClass>
并检查它是否有效。
我仍然建议您按照 Benjamin 的建议使用 2/3。只是一个小小的补充。
推荐阅读
- git - 合并 GIT 中的两个存储库时无法在一定时间内保留历史记录
- amazon-web-services - AWS 网络负载均衡器重定向端口
- css - SAPUI5 UI 表格滚动条宽度和高度问题
- pdf - Ghostscript PDF 优化导致内存问题
- python - 大熊猫的 urlib.parse.quote
- dolphindb - 为什么修改密码后新旧密码都能登录成功?
- php - WooCommerce 5.5.2 上的自定义价格
- javascript - 如何在 Django 中将用户交互数据发送到数据库
- node.js - MongoDB 文本搜索不起作用(节点 js)
- amazon-web-services - 没有 API 的 S3 put 操作