2017-07-31 57 views
0

我有一個類在其析構函數中完成一個動作。 它在調用另一個函數等的單獨的類的函數中調用。什麼時候使用QTimer調用多個函數調用的析構函數?

void method3() 
{ 
    //action gets done 
} 

void method2() 
{ 
    //action gets done 
    method3(); 
} 

void method1() 
{ 
    obj o; 
    //action gets done 
    QTimer::singleShot(1000, this, SLOT(method2())); 
} 

不使用QTimer::singleShot,只是調用method2()method3()完成後調用析構函數。

什麼時候使用QTimer::singleShot調用method2()時obj的析構函數被調用? 是否有使用QTimer::singleShot並且在method3()的末尾有正常調用的析構函數?

+3

不完全正確:在兩種情況下,method1完成時調用析構函數。當你使用異步機制如QTimer(免責聲明我對QT一無所知,但是從基本C++原則的知識來講)時,基於本地堆棧的對象的生命週期結束時,它們的創建範圍就結束了。如果你想延長對象的生命週期,它首先需要基於堆(忽略全局變量)。您最好的選擇是使用共享指針並將其傳遞給method2,然後將其作爲原始指針或對method3的引用,因爲它是同步調用的。 –

回答

0

o具有automatic storage class,這意味着它在封閉塊結束時釋放:

void method1() 
{ 
    obj o; 
    //action gets done 
    QTimer::singleShot(1000, this, SLOT(method2())); 
} // o ceases to exist here 

method2計劃在未來某一時刻運行,method1返回之後值得注意的是,這樣的自動變量的聲明method1的信息現在不能提供。

如果需要o堅持你可以

  • 聲明o作爲類的成員,如method1似乎是某個類的成員函數

  • new分配它,或者更好,使用智能指針(可能是std::unique_ptr將是最適合的),並在不再使用時手動釋放它。

1

由於obj類型的o對象具有自動storage durationmethod1範圍內時,它會被當提到範圍結束破壞,即method1飾面。

在第一種情況下,當您撥打method2而沒有QTimer::singleShot時,您只是執行了一次正常的函數調用,它將返回到method1。因此,當method2返回時,method1將完成。

在第二種情況下,您通過呼叫QTimer::singleShot創建了一個事件,該事件將在事件創建後立即返回,因此method1將在method2的呼叫發生之前完成。

太延長o對象的生命週期,你必須與動態存儲時間創建它,那麼當method3完成摧毀它。這可以通過newdelete運營商完成,但我建議使用QSharedPointer或其他智能指針。

這是我解決您的問題:

#include <QSharedPointer> 
#include <QTimer> 
#include <QtDebug> 
#include <QObject> 

class obj { 
public: 
    obj() { qDebug() << "Instance of 'obj' is created."; } 
    ~obj() { qDebug() << "Instance of 'obj' is destroyed."; } 
}; 

class Foo : public QObject { 
    Q_OBJECT 
public slots: 
    void method3() { 
     qDebug() << "Foo::method3 called."; 
     m_obj.reset(); // destroys the previously created 'obj' instance 
    } 
    void method2() { 
     qDebug() << "Foo::method2 called."; 
     method3(); 
    } 
    void method1() { 
     m_obj.reset(new obj); // creates a new 'obj' instance 
     qDebug() << "Foo::method1 called."; 
     QTimer::singleShot(1000, this, SLOT(method2())); 
    } 
private: 
    QSharedPointer<obj> m_obj; 
}; 
0

在這種情況下,您可以創建o只有當定時器的實際激活。當定時器的實際激活(執行該拉姆達)不是當method1()被稱爲

void method1() 
{ 
    QTimer::singleShot(1000, this, [this] 
    { 
     obj o; 
     // Do your stuff here. 
     method2(); 
    }); 
} 

這裏,不僅創造o:您可以使用一個lambda函數。

如果這不適合您的用例,並且在調用method1()時確實需要創建對象,而不是在定時器激活時創建該對象,則可以使用共享指針來防止在定時器觸發之前銷燬對象:

#include <memory> 
// ... 

void method1() 
{ 
    auto o_ptr = std::make_shared<obj>(/* ctor arguments here */); 
    // Do your stuff here. 

    QTimer::singleShot(1000, this, [o_ptr, this]{ method2(); }); 
} 

由於我們拍攝的拉姆達o_ptr,對象是不會被破壞。它只會在拉姆達完成後被銷燬。 shared_ptr保證如果任何人仍然持有對shared_ptr的引用,則其保存的對象不會被銷燬。在這種情況下,lambda持有一個引用來保持對象的活着。一旦lambda完成執行,引用被釋放並且對象被銷燬。

相關問題