是否有任何技巧可以检测在执行另一个析构函数期间是否创建了一个对象?

时间:2013-02-18 15:34:18

标签: c++ destructor uncaught-exception stack-unwinding

这是对Why can't Alexandrescu use std::uncaught_exception() to implement SCOPE_FAIL in ScopeGuard11?

的跟进

我想检测某人是否在另一个类的析构函数中创建MyClass(或者在调用堆栈中的某个地方使用了一个活动的析构函数)。

class MyClass
{
public:
    MyClass(){
        assert(???what to put here????);
    }
}

void f(){
    MyClass m;    //whether this asserts should be context dependant
}

class OtherClass{
    ~OtherClass(){
        MyClass m; //this should assert
        f();       //this should too;
    }
}

int main()
{
    MyClass m;   //this should not assert
    f();         //this should also not assert
}

一次尝试可能是:

assert(!std::uncaught_exception());

但是只有在因为异常而调用析构函数时才会有效,而不是因为对象超出范围而被调用。

2 个答案:

答案 0 :(得分:1)

你无法检测到这一点,你不想这样做。这不是你班级的事。如果有人会从noexcept析构函数中调用你,他将捕获异常

答案 1 :(得分:0)

除非您让呼叫者提供该信息,否则无法检测您的功能是如何被调用的。

另外,我记得Visual C ++从未实现过std::uncaught_exception,因此即使知道没有析构函数调用任何try块,也是如此(对于可移植代码)。

然而,检测范围是否因异常而退出是微不足道的。

只需将该范围放在try - 块中;这就是它的用途。

例如,

class Transaction
{
private:
    bool failed_;
    Transaction( Transaction const& );  // deleted
    Transaction& operator=( Transaction const& ); // deleted

public:
    void fail() { failed_ = true; }

    void commit() { ... }

    // More functionality, then

    ~Transaction()
    {
        if( failed_ ) { rollback(); }
    }

    Transaction(): failed_( false ) {}
};

void foo()
{
    Transaction transaction;

    try
    {
        // blah blah
    }
    catch( ... )
    {
         transaction.fail();
         throw;
    }
}

免责声明:我没有使用过该模式,因此无法证明它的实用性。