如果其中任何一个抛出
class X {
string m_str;
X() : m_str("foo")//what if this throws?
{
ifstream b("a.in")//what if this throws?
}
那么您创建的对象将不存在。
如果在对象的构造函数中引发异常,则所有完全创建的成员都会被析构(使用其析构函数),并且该对象的内存将返回给系统。因此,任何在抛出点未完全构造的成员都不会被销毁(因为它们尚未创建)。
- 如果 m_str() 在初始化列表中抛出,那么该对象将永远不存在。
- 如果 ifstream 在主体中抛出异常,那么 m_str 就会被销毁,并且该对象将永远不会存在。
我应该将代码包装在 catch(exception &) 中吗?如果我这样做,string 和 ifstream 是否能保证强有力的保证,即不会泄漏任何资源,也不会留下任何半打开的东西?
即使您捕获异常(在对象外部),也没有对象可以处理,因为它从未存在过(对象仅在构造函数完成后才开始其生命周期)。
在上述内容中,您可以保证没有泄漏或开放资源。
另外,如果我的类抛出 myException,它是从异常派生的,catch(exception &) 似乎会让它通过。这样我就剩下了 catch(...) IIRC 捕获访问冲突?.?还有别的办法吗?
如果您的异常源自 std::exception 那么catch(std::exception&)
将工作。如果它不起作用,那么你做错了什么(但我们需要更多细节(例如抛出的代码和捕获的代码,英语描述是不够的))。
然后有一条信息表明,在对象构造函数的子构造函数中抛出的任何异常都不应该被捕获,并且构造函数应该在任何成员对象抛出异常的情况下抛出。
可能是最好的选择,而且一般来说,建议也不错。
如果上面的代码不是从构造函数调用,而是从常规函数 void foo() 调用,我应该捕获哪些异常呢?内存不足,文件未找到?在哪里可以找到 STL 对象可以抛出的定义?它们是具体实施的吗?
仅当您可以采取措施时才应捕获异常。通常这没什么,所以不要捕获它们,让应用程序正常退出(通过异常展开堆栈)。
哪里有权威的来源可以消除我对此主题的所有疑虑和疑问?
你的问题是如此多样化,这很难。
我可以推荐Herb Sutter 的《卓越的 C++》 http://www.gotw.ca/publications/xc++.htm.
到目前为止,处理异常似乎就像在一大堆黏糊糊的东西里跳舞。错误代码看起来更简单、更安全......
你错了。例外要容易得多。你似乎只是想太多并且感到困惑。这并不是说错误代码没有它们的位置。
如果出现问题and you can not fix it locally
然后抛出异常。标准中的所有类在设计时都考虑到了异常,并且会正常运行。这样就只剩下你的课程了。
经验法则:(针对您的对象)
- 确保你的类在析构函数中自行清理
- 如果您的对象包含资源,请确保“遵守 3 规则”
- 每个对象永远不要拥有多个资源。
注意:您可以拥有多个东西,例如 std::string 或 std::ifstream ,因为它们是控制资源的东西(它们各自控制一个资源,因此您的类不控制该资源)。资源(在此上下文中)是您必须手动创建/销毁的东西。
就这样,其余的自动神奇地工作了。