Qt信号/插槽:从临时对象发出信号是错误的吗?

Dan*_*aum 6 c++ qt signals-slots

在Qt中,如果从临时对象调用信号,这样在调用插槽时可能会删除该对象,这是一个错误吗?

如果它是相关的,代码将从临时对象的构造函数发出信号.

(注意:没有指针或引用作为参数传递,所以这不是关于悬空指针或引用的问题.我只想知道,以最简单的形式,是否可以从临时对象发出信号在Qt.)

这是我的代码的缩短版本:

// My application
class HandyApplication: public QApplication
{
    Q_OBJECT
    public:
        explicit HandyApplication( int argc, char * argv[] );

    signals:

    public slots:
        void handySlot(std::string const msg);

};

// Class that will be instantiated to a temporary object
class Handy: public QObject
{
    Q_OBJECT

    public:

        Handy()
        {
            QObject::connect(this, SIGNAL(handySignal(std::string const)), 
                 QCoreApplication::instance(),
                 SLOT(handySlot(std::string const)));

            emit handySignal("My Message");
        }

    signals:

         void handySignal(std::string const msg);

};

// An unrelated function that may be called in another thread
void myFunction()
{
    Handy temporaryObject; // This constructor call will emit the signal "handySignal" above
}
Run Code Online (Sandbox Code Playgroud)

如您所见,临时对象从其构造函数发出信号,然后立即销毁. 因此,可以在发送信号的对象被破坏之后调用时隙.

这是安全的,还是潜在的问题或错误情况?

jdi*_*jdi 4

您指定的是从信号到插槽的直接连接。这意味着在您发出的那一刻handySignal,它应该去执行所有连接的插槽。一旦所有插槽(即handySlot)返回,发射器将返回并完成构造函数。

如果您要指定一个排队连接(如果它是从一个线程中的信号到另一个线程中的槽的连接),那么该请求将被放入要执行的事件循环中。

所以我想说:是的,如果您不传递无效的引用,那么从临时对象发出信号似乎很好。

这个例子似乎有点武断,因为我真的没有看到在构造函数中与信号建立连接的意义,然后发出信号,仅此而已。您也可以只调用该槽,除非您希望在不同的线程中创建该对象,而您没有提到这一点。

编辑:

根据@Kamil的评论,应该注意的是,如果未指定连接类型,则默认为自动连接,这意味着实际类型将取决于目标槽是否与发送者位于不同的线程中。如果没有线程,它将等同于 DirectConnection。通过线程,它最终将成为一个 QueuedConnection。

  • 您*需要*调用是同步的还是异步的,或者您只是不在乎?在前一种情况下,您不妨调用方法 (`obj->method(args)`); 后者使用“QMetaObject::invokeMethod”和“QueuedConnection”来强制在返回事件循环时发生调用。 (2认同)