什么时候异常对象被破坏(并且可以被控制)?

时间:2015-08-20 15:32:20

标签: c++

我正在为容器写一个替换品,而我正在努力 获得所有例外保证。我现在正在写作 clear方法,我希望它尽可能地完成, 并且始终将容器保持在一致状态,即使 其中一个析构函数抛出异常。我也想重新抛出 我完成清洁后的例外,最好没有切片。

这让我想到了这个问题;什么时候被破坏了? 让我们看看一次尝试: 这个例子简化了。

void container::clear()
{
    bool had_exception = false;
    std::exception* exp;
    internal_set_empty(); // this cant throw
    while( ! internal_done() )
    {
        try
        {
            internal_destruct_next(); // this might throw if T::~T() throws
        }
        catch( std::exception& e )
        {
            had_exception = true;
            exp = &e;
        }
    }
    if( had_exception )
        throw *exp;
}

我希望这会失败,因为异常可能会被破坏 当它被认为是处理时,这在技术上并没有重新抛出。

另一种尝试是获取异常的副本,就是这样 我希望会切片。

有没有办法延长异常的生命周期,以便我可以重新抛出 它以后呢? 如果可能的话,我也希望能够重新抛出捕获的异常 通过catch(...)

2 个答案:

答案 0 :(得分:4)

  

即使其中一个析构函数抛出异常

无法完成。析构函数不是出于某种原因 - 你无法从抛出的析构函数中恢复。很明显,你没有做任何事情来清理破坏者抛出的物体 - 因为你怎么能尝试这样做 - 但这也意味着你只是让他们在僵尸状态下闲逛。

在您更具体的问题上,您可以使用递归来保留catch的堆栈框架以尝试继续删除元素,或者您也可以使用C ++ 11中的std::exception_ptr和朋友来传输异常周围。

答案 1 :(得分:1)

将异常传递给调用者的当前用法是在catch块中重新抛出它。假设你有充分的理由不这样做,唯一正确的方法是使用std::exception_ptr。仅仅std::exception*存在很高的风险,即异常被销毁并且在您再次抛出异常之前释放其内存。

标准C ++ 2011草案(n4296)在15.1处说抛出异常§4:异常 在异常的最后剩余活动处理程序以任何其他方式退出之后,对象将被销毁 而不是重新抛出,或引用异常对象的std :: exception_ptr类型的最后一个对象是 销毁,以较晚者为准。在前一种情况下,当处理程序立即退出时会发生破坏 破坏在处理程序中的exception-declaration中声明的对象之后,如果有的话。在后者 在这种情况下,破坏发生在std :: exception_ptr的析构函数返回之前。实施 然后可以为异常对象释放内存;任何此类解除分配都是在未指定的情况下完成的 方式(强调我的)