我有一个关于失败的构造函数和C ++中的析构函数失败的问题。
我注意到当构造函数失败时,将抛出异常。但析构函数中没有异常抛出。
我的问题是
1)如果构造函数失败,将抛出什么异常? bad_alloc的?或其他相关的?在什么情况下,构造函数会失败?成功构建的部分怎么样?
2)在什么情况下,析构函数会失败?如果没有抛出异常,析构函数会发生什么?编译器如何处理它?它被称为函数的返回值是什么?
谢谢!
非常感谢任何评论!
答案 0 :(得分:6)
如果构造函数失败,则仅在实现构造函数时抛出异常才会引发异常。 (您可能需要区分内存分配和构造。使用new
分配内存可能会导致std::bad_alloc
异常失败。)
一般情况下,构造函数都不会失败。只有在写入时才会失败,它才会失败。如果是这样,它的失败取决于它是如何写的。通常,应该编写析构函数,以便它们不会失败,因为从析构函数中抛出异常是不安全的。 (那是因为它们可能在堆栈展开期间被调用。)
请注意,问题中使用的“失败”通常是指运行时故障。所以编译器与它无关。此外,构造函数和析构函数都不会返回任何内容。
答案 1 :(得分:2)
构造函数失败时抛出的异常由构造函数本身决定,因为它直接抛出,或者由它执行的操作抛出(比如调用可能引发异常的另一个函数)。
构造函数在尝试获取不可用的资源(例如内存,文件句柄,屏幕窗口等)时可能会失败。如果new
失败,它将抛出std::bad_alloc
。如果构造函数没有捕获它,那么它将传播出构造函数。
C ++没有很好的方法来处理析构函数中的错误。在可能的范围内,您应该设计析构函数以避免失败。你永远不应该从析构函数中抛出异常。如果你在析构函数中调用的函数可能抛出异常,你应该捕获它(如果你知道它可以安全忽略)或立即崩溃。
答案 2 :(得分:2)
如果你的析构函数抛出异常,你就会做错事。在析构函数中抛出异常可能会导致几个问题区域:从套接字/线程/对象池中使用的项可能会永久陷入难以置换的状态,内存可能无法释放,或者由于某种原因您置于析构函数中的逻辑可能不会被叫。
在其他地方的代码中抛出异常的所有相同原因都可能导致在析构函数中抛出异常。最值得注意的是,如果你有一个悬空指针试图清理当前使用的内存,可能会导致系统异常。祝你好运。
答案 3 :(得分:1)
此上下文中的构造函数“只是”一个用户函数,它可以抛出它想要的任何异常。如果构造函数没有抛出异常,则认为它没有失败。
所以:构造函数本身不会失败。如果它本身抛出异常,则失败。如果没有,编译器不会隐式添加特殊代码来抛出任何异常。
对于析构函数也是如此。
答案 4 :(得分:1)
如果构造函数失败,那么它会抛出一些异常。它不一定是因为无法分配内存;任何会引发异常的东西都会使它失败,包括你自己编写的throw
语句。这个想法通常是创建一个可用的对象或抛出异常。
如果构造函数失败,则没有成功构造的部件。一切都消失了。
我不知道析构函数失败是什么意思。它将执行任何适用的代码,并且不返回任何内容。如果代码编写得很糟糕,它可能无法完成程序员想要的操作,但所有函数都是如此。
析构函数永远不应该抛出异常。 (它们可以调用抛出的例程,但它们应该捕获所有异常并自己处理它们。)如果析构函数抛出,并且因为抛出异常并且它正在展开堆栈而调用它,程序会以某种方式崩溃。 (有一些机制可以尝试判断堆栈是否正在展开,但最好是两种不同的方式编写析构函数,并且很难对它们进行测试。)
答案 5 :(得分:1)
除了这里提到的所有内容之外,operator new可以在调用构造函数之前抛出bad_alloc。构造函数只在存在一个存在对象实例的内存之后才开始运行(尽管在构造函数完成之前它并不完全存在)。