理解C++中的'try'关键字

3
考虑以下代码:

#include <iostream>
#include <stdexcept>

class E{
    public:
        E(int n):m_n(n)
    {
        if (0>n)
        {
            throw std::logic_error("5");
        }
    }
        ~E(){cout << m_n << "#" <<endl;}
    public :
        int m_n;
};

int main()
{
    try{
        E a(5);
        try{
            E c(7);
            E b(-8);
            E d(9);
        }
        catch(const std::exception &e)
        {
            cout <<2 <<"&&&"<<e.what()<<endl;
            throw e;
        }
    }
    catch(const std::exception &e)
    {
        cout <<3 << "^^^^^ "<<e.what() << endl;
        throw e;
    }
    return 0;
} 

我得到的输出是:
7#
2&&&5
5#
3^^^^^ St9exception
std::exception: St9exception
Aborted.

请问为什么会得到这样的输出?我希望看到前五个#符号。


4
缩进代码,你几乎可以立即弄清楚它。 - StoryTeller - Unslander Monica
2
销毁的顺序与创建相反。 - PlasmaHH
4
谁起源了那些 Yoda 条件语句?每次我都必须重写这些条件语句,我的大脑都会感到不适。 - Najzero
3
因为人们会把它用来关闭完全有效的问题,就像这个问题一样(尽管我个人认为如果Gaurav解释一下他为什么期望先打印5#,那就更好了,但这与是否过于局部化无关)。 - sepp2k
2
@Najzero:有人注意到一个偶然的 if (i=0) 最多只会产生一个警告,但是 if (0=i) 则会导致编译错误。 - Frerich Raabe
显示剩余6条评论
3个回答

5
以下是您程序的伪代码工作流程:
{
  //outer try
  create e(5);
  {
    //inner try
    create e(7);
    failed create e(-8);//exception here
    throw;
    delete e(7);//-> 7#
  }
  {
    //catch in inner try;
    cout &&&;//-> 2&&&5
    throw e; // throw sliced copy of original exception
  }
  delete e(5);//-> 5#
}
{
  //catch in outer try
  cout ^^^^;//-> 3^^^^^ St9exception (the last thrown is pure std::exception)
  throw e; // throw another copy, no more slicing as it's already exception
}
program termination because of uncaught exception;
//-> std::exception: St9exception
//-> Aborted.

//return 0; was never reached

0

由于构造b失败,这导致已经存在的c被销毁,然后执行内部catch。

由于它重新抛出异常,因此外部try中已经存在的a被销毁并执行外部catch。

由于它再次重新抛出异常,并且没有更多的catch,所以异常跳出main(),由支持库处理并打印消息并终止程序。

销毁顺序与构造顺序相反。因此,在a之后构建的c在其之前被销毁。

bd从未启动。


0

a 被析构时将会显示 #5。这将在 c 被析构后发生,这发生在 堆栈展开 之后,而您已经显示了 e.what()


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