2017-07-31 163 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完成执行,引用被释放并且对象被销毁。

相关问题