2013-05-18 39 views
6

在Qt中,如果從一個臨時對象調用一個信號,這樣該對象可能會在該槽被調用的時候被刪除,這是錯誤嗎?Qt signals/slots:從臨時對象發出信號是否是錯誤的?

如果相關,代碼將發出來自臨時對象構造函數的信號。 (注意:沒有指針或引用作爲參數傳遞,所以這不是關於懸掛指針或引用的問題,我只是想知道,如果以最簡單的形式發出一個信號是可以接受的從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

你指定的是從信號到插槽的direct connection。這意味着此刻你發出handySignal,它應該去執行所有連接的插槽。一旦所有的插槽(即handySlot)都返回,發射器將返回並完成構造函數。

如果要指定一個queued connection(如果它是從一個線程中的信號到另一個線程中的信號的連接),那麼該請求將被放置到要執行的事件循環中。

所以我會說:是的,從臨時對象發出信號似乎很好,如果您沒有傳遞無效的引用。

這個例子似乎有些隨意,因爲我沒有真正意識到在構造函數中建立一個連接到一個信號,然後發出的信號,這就是它。您可能只需調用該插槽,除非您希望在不同的線程中創建該對象,而您並未提及該線程。

編輯:

按照由@Kamil的評論,但是應當注意的是,如果沒有指定一個連接類型,然後用是自動連接的,這意味着實際的類型將被確定的defailt根據目標插槽是否在與發送者不同的線程中。沒有線程,它將等同於DirectConnection。使用線程,它最終將成爲QueuedConnection。

+0

這不是真的,如果信號是從一個不同的線程發出的,而不是調用該槽的線程,* emit *調用可能是異步的? –

+0

@DanNissenbaum:雅這就是我說的話。當它在不同的線程中時,它變成排隊的連接。但即使情況如此,如果信號不是發射可能無效的物體,那也沒有問題。無論發送者如何,該調用都會被註冊到目標線程事件循環中並被調用。 – jdi

+2

你需要*呼叫是同步還是異步,或者你只是不在乎?在前一種情況下,你可能只需調用方法('obj-> method(args)');在後者使用帶有QueuedConnection的'QMetaObject :: invokeMethod'來強制在返回事件循環時發生調用。 – peppe

1

我會說從一個臨時的物體發射是安全的,因爲QObject::destroyed「obj對象被銷燬前被立即發出」 - Qt docs

所以大概從一個臨時的物體發出的信號將是安全和適當的。

相關問題