gpt4 book ai didi

c++ - 在析构函数和后续析构函数中抛出异常

转载 作者:行者123 更新时间:2023-12-04 07:33:24 26 4
gpt4 key购买 nike

我做了一个从析构函数抛出异常的实验,得到了一个我没有预料到的结果。查看代码片段:

#include <iostream>
#include <exception>

class A
{
public:

~A() noexcept(false)
{
std::cout << "in ~A" << std::endl;
//throw std::runtime_error("~A exception");
}
};

class M
{
public:

~M() noexcept(false)
{
std::cout << "in ~M" << std::endl;
//throw std::runtime_error("~M exception");
}
};

class B : public A
{
public:

~B() noexcept(false)
{
std::cout << "in ~B" << std::endl;
throw std::runtime_error("~B exception");
}

private:

M m;
};

class X
{
public:

~X() noexcept(false)
{
std::cout << "in ~X" << std::endl;
//throw std::runtime_error("~X exception");
}
};

int main()
{
try
{
X x;
B b;
}
catch(const std::exception& e)
{
std::cerr << e.what() << '\n';
}

return 0;
}
输出:
in ~B
in ~M
in ~A
in ~X
~B exception
0
所以问题是:如果我从析构函数中抛出异常,它会被捕获,然后所有后续的析构函数(包括基类的析构函数、类成员和堆栈上声明的对象的析构函数(如 X、例如)) 被调用,然后重新抛出异常?
编辑 1:
如果我修改 main(),结果相同如下:
int main()
{
try
{
X x;
B * b = new B();
delete b;
}
catch(const std::exception& e)
{
std::cerr << e.what() << '\n';
}

return 0;
}

最佳答案

and then the exception is rethrown?


不,它不是“重新抛出”。析构函数被调用 作为 的一部分抛出(并捕获)异常。这在语义上略有不同,但这里只抛出一次异常,并且对象在抛出异常的过程中被销毁。
让我们抛开从析构函数抛出异常的问题(这本身就是一个不确定的话题)。考虑以下代码:
void function()
{
X some_object;

throw std::runtime_error("bad");
}
X的析构函数在此处作为抛出异常的一部分被调用。为什么?因为对象正在被破坏。如果此函数 return,则调用析构函数与调用析构函数没有什么不同。正常。唯一的区别是,不是返回调用者,而是返回到异常被捕获的地方(假设它被捕获)。但是,无论哪种方式,执行都会离开此范围,这意味着必须销毁自动范围内的对象,这意味着必须调用其析构函数。
每当执行离开对象的自动范围时,就会调用自动范围对象的析构函数。范围是自愿离开,还是由于抛出异常而非自愿离开,没有区别。
在你的情况下,这没有什么不同。事实上,您的代码已经进入了最派生对象的析构函数,作为正常销毁它的一部分(通过 delete 或通过离开自动对象的范围)。抛出异常的事实并没有真正改变对象被销毁的事实。唯一的区别是对象作为抛出异常的一部分被销毁,因为执行移动到它被捕获的地方,但是执行移动到它返回的地方,或者它的异常被捕获的地方,对于析构函数调用。

关于c++ - 在析构函数和后续析构函数中抛出异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67851343/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com