6

在 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
}

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

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

4

2 回答 2

4

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

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

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

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

编辑:

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

于 2013-05-18T03:46:20.920 回答
1

我会说从临时对象发射是安全的,因为QObject::destroyed“在对象 obj 被销毁之前立即发射” - Qt docs

因此,从临时对象发出的信号大概是安全和适当的。

于 2016-09-13T15:29:36.793 回答