删除信号发送的对象,信号中对象的所有权,Qt

时间:2010-07-06 05:58:18

标签: c++ qt signals-slots qt-signals

在这里,我的信号声明:

signals:
    void mySignal(MyClass *);

我是如何使用它的:

MyClass *myObject=new myClass();
emit mySignal(myObject);

我的问题出现了:谁负责删除myObject:

  1. 发件人代码,如果在使用myObject之前删除了什么?悬空指针

  2. 连接到信号的插槽,如果没有插槽或连接到信号的多个插槽怎么办?内存泄漏或悬空指针

  3. Qt如何在其内置信号中管理这种情况?它是否使用内部引用计数?

    您的最佳做法是什么?

4 个答案:

答案 0 :(得分:10)

您可以根据需要连接多个插槽的信号,因此您应该确保这些插槽中没有一个能够执行您不希望他们对您的对象执行的操作:

  • 如果您决定将指针作为参数传递,那么您将运行您描述的问题,内存管理 - 这里没有人可以为您工作,因为您必须建立处理分配/删除的策略。有关如何解决此问题的一些想法,请参阅COM世界中的内存管理规则。
  • 如果您决定将参数作为参考传递,那么您不必担心内存管理,而只需要担心以意外方式修改对象的插槽。除非必须,否则ideea不会传递指针 - 如果可以,请使用引用。
  • 如果您决定传递const引用,那么根据您的连接类型,QT会为您传递对象的值(有关详细信息,请参阅this
  • 避免任何问题并通过值传递:)

有关在信号中传递指针的一些想法,请参阅此question

答案 1 :(得分:5)

关于第一个问题,请使用QPointer

关于第二个问题,

如果我清楚地理解,即使您发送myObject仍会在您发出信号的班级中有参考 myObject。那怎么会是内存泄漏还是悬空指针?你仍然可以访问来自发布的类的myObject,不是吗?

希望很清楚..

编辑:

从您的评论中我相信您正在发布/删除插槽中的对象。现在我假设你的问题是,如果(内存释放)插槽被调用一次,两次或根本没有被调用,该怎么办。

您可以使用QPointer。从Qt文档中,

当您需要存储指向其他人拥有的QPointer的指针时,有保护的指针(QObject)非常有用,因此当您仍然保留对其的引用时可能会将其销毁它。您可以安全地测试指针的有效性。

Qt文档本身的一个例子,

     QPointer<QLabel> label = new QLabel;
     label->setText("&Status:");
     ...
     if (label)
         label->show();

解释继续这样......

如果在此期间删除QLabel,则标签变量将保留0而不是无效地址,并且最后一行将永远不会被执行。此处QLabel将是您的MyClass和标签是你的myObject。在使用之前,请检查 Nullity

答案 2 :(得分:3)

在1):发件人应该小心。当同步发送信号(而不是排队)时,当接收器接收到该对象时,该对象仍然存活。如果接收者需要存储它,只有QPointer会有所帮助,但是MyClass需要从QObject派生,这从上下文看起来是错误的。 无论如何,这是一般的终身问题,而不是信号/插槽特定的。

替代方案:使用值类并通过const引用发送它。如果MyClass可以有子类,则传递const QSharedPointer&amp;

关于deleteLater:deleteLater()在这里没有帮助。它会使排队的连接更安全,对于直接连接,它没有任何区别。 deleteLater()发挥作用的一个用途是接收者是否需要删除发送者。然后应该总是使用deleteLater(),这样发送者就可以完成他正在做的事情,否则会崩溃。

答案 3 :(得分:0)

总之(好吧,函数名) - deleteLater():)所有QObject都有它。它将标记要删除的对象,然后在下一个事件循环更新时发生。