在QObject构造函数中使用运算符'new'(多线程)

时间:2014-02-16 12:25:41

标签: multithreading qt

This article详细说明QThread的“正确”用法

  

顺便提一下,这里要注意的一件非常重要的事情是你永远不应该在QObject类的构造函数中分配堆对象(使用new),因为这个分配然后在主线程上而不是在新的QThread实例上执行,意味着新创建的对象随后由主线程而不是QThread实例拥有。这将使您的代码无法正常工作。相反,在这种情况下,在主函数槽中分配这样的资源,例如process(),因为当调用该对象时,它将在新的线程实例上,因此它将拥有该资源。

我理解第一部分是堆对象的分配(从而运行构造函数)发生在创建QObject的线程中。之后才使用QThread :: moveToThread将其推送到QThread。

但是我不太明白所提到的所有权问题,特别是

  

意味着新创建的对象随后由主线程

拥有

肯定不是指资源的标准所有权,因为在Qt中可以通过父子机制轻松控制。

它是否意味着多线程(或QThread)的底层内存管理机制,尽管这只是我所知道的OS'线程实现的包装器?因为存储资源的每个线程都有不同的“内存段/缓存”?

如果是这种情况我可以看到问题,但我找不到完整的答案或解释。谢谢!

1 个答案:

答案 0 :(得分:7)

它指的是QObjects存在于某些线程中的事实 - 默认情况下,创建它们的线程。 “实时”指的是QObject不是可重入的也不是线程安全的:QObject只能从它所在的线程中使用。

但是,建议是错误的。

是完全安全的
class Foo : public QObject {
    Q_OBJECT
    Foo() {
        m_suboject = new Bar(this);
        m_other = new Fie("/dev/blah", this);
        ...

关键在于this参数,这意味着子对象正确地为Foo实例的父级。因此,当你做

Foo *foo = new Foo;
foo->moveToThread(thread);

以“foo”为根的整个对象树将被移动到新线程中(moveToThread移动一个对象及其所有子对象)。