在抛出期间构造对象时引发异常
Throwing an exception while constructing object during a throw?
我有一个异常类:
class MyException : public std::exception
{
public:
MyException( char* message )
: message_( message )
{
if( !message_ ) throw std::invalid_argument("message param must not be null");
}
};
在我的投掷现场:
try {
throw MyException( NULL );
}
catch( std::exception const& e ) {
std::cout << e.what();
}
(代码未编译,因此请原谅任何错误(
我想知道当我在构造时由于另一次抛出而从构造函数中抛出时会发生什么。我认为这是合法的,并且捕获最终会捕获一个std::invalid_argument
,并且之前抛出的异常(MyException
(将被忽略或取消。
我使用此设计的目标是在我的异常类中强制实施不变量。 message_
永远不应该是 NULL,而且我不想在我的 what()
重载中使用 if 条件来检查它是否为 null,所以我在构造函数中检查它们并在它们无效时抛出。
这是正确的,还是行为不同?
你打算抛出的对象(在本例中为 MyException
(必须先成功构造,然后才能抛出。所以你还没有扔掉它,因为它还没有被构建出来。
所以这将起作用,从MyException
的构造函数中抛出异常。不会触发"处理异常时引发异常导致std::terminate
"问题。
15.1 抛出异常 n3376
第7段
如果异常处理机制在完成对要抛出的表达式的计算后但在捕获异常之前调用通过异常退出的函数,则调用 std::terminate (15.5.1(。
这意味着在构造函数(在本例中被抛出的对象(完成之前,不会发生任何特殊情况。但是在构造函数完成后,任何其他 uncought 异常都将导致调用terminate()
。
该标准继续提供了一个示例:
struct C
{
C() { }
C(const C&) { throw 0; }
};
int main()
{
try
{
throw C(); // calls std::terminate()
}
catch(C) { }
}
这里调用终止是因为对象是首先创建的。但随后调用复制构造以将异常复制到保留位置 (15.1.4(。在此函数调用(复制构造(期间,将生成未捕获的异常,从而调用终止。
因此,如图所示的代码应按预期工作。
- 任一项:生成一个带有良好消息的
MyException
并抛出 - 或者:生成并抛出
std::invalid_argument
如果要检查应始终为真的不变量,则应使用断言。异常适用于预期会发生的异常情况,例如极端情况或错误的用户输入。
如果使用异常来报告代码中的错误,则可能会意外地使用 catch(...( 隐藏它们。如果您正在编写库代码,这一点尤其重要,因为这样您永远不知道其他人是否会捕获并忽略异常,即使这意味着系统已达到无效状态。
断言的另一个优点是,如果需要,可以完全禁用它们,这样它们就不会再产生任何性能损失。这使您对调试版本中的这些检查非常偏执,并且仍然拥有闪电般的快速发布版本。
- 关于:C++中异常对象的范围:为什么我没有得到副本?
- 创建具有 new in 函数和"this is nullptr"异常的对象
- 对象初始化后在C++中显示 char 数组时的异常行为
- 如何捕获 C++ 内置异常对象
- 对象接收堆栈溢出异常 c++ 的排序向量
- 堆异常 -1073741510对象
- std::bad_weak_ptr对象构造后shared_from_this异常
- 如何捕获源自静态分配对象的构造函数的异常?
- 基于对象的两个属性的自定义比较器会引发异常
- 如果一个对象是在本地创建的,并在C++中作为异常抛出,那么本地对象如何在其范围之外有效,即在 catch 块中?
- 为什么内置类型的对象上的溢出会导致异常/未定义的行为?
- 如何防止构造函数在引发异常时创建对象
- std::system 实例化单一实例对象时的异常
- 异常对象的最后一个潜在销毁点
- 初始化引发异常的对象
- 调试器在异常C++时未挂起调试对象
- 通过引用派生类对象从基类对象执行向下转换时引发bad_cast异常
- 在 C++ 中的构造函数中引发异常时销毁对象的成员变量
- C++ 异常处理:将异常定义为对象
- 从函数中抛出内部对象异常合法吗