在执行另一个析构函数期间,有没有什么技巧可以检测到对象是否被创建?

11

这有点是对为什么Alexandrescu不能使用std::uncaught_exception()来实现ScopeGuard11中的SCOPE_FAIL?的跟进。

我想检测是否有人在另一个类的析构函数中(或在调用堆栈的某个活动析构函数中)创建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());

但是这仅在析构函数由于异常而被调用时才有效,如果它是因为对象超出范围而被调用,则不起作用。


7
除非你明确地设计了那些析构函数以任何方式发出它们的执行信号,否则我怀疑这是不可能的。一般来说,你无法知道你的函数是从哪里调用的。 - Andy Prowl
你希望这个解决方案有多高的可移植性? - Flexo
你可以将解决方案专门针对特定编译器版本,然后在 MyClass 的构造函数中检查堆栈,以查找 OtherClass 的析构函数。我个人认为这太费力了... 而且会产生错误。 - Synxis
我曾担心可能没有一个好的答案,但是我总是惊讶于人们在元编程中想出了多少复杂的技巧。谁知道,也许会有一个像Alexandrescu 2.0一样的人出现,让我们大跌眼镜。 - odinthenerd
@Damon:模板没用,模板会复制代码,但每次只能使用一个副本。 - Mooing Duck
显示剩余3条评论
2个回答

1

你无法检测到这个,也不想要。这不是你的类的事情。如果有人从noexcept析构函数中调用你,他会捕获异常。


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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接