我在哪里可以找到有关C++/STL方法异常保证的信息?

Cod*_*der 8 c++ exception-handling

前几天我正在编写带有异常处理的代码,我有一些关于异常,它们的保证和抛出的问题.

基本上,说你有:

class X {
string m_str;
X() : m_str("foo")//what if this throws?
{
    ifstream b("a.in")//what if this throws?
}
Run Code Online (Sandbox Code Playgroud)

在浏览了我能找到的所有文章之后,我仍然不知道处理这个问题的干净方法是什么.

说我有一个像这样的代码:

{
    ...
    X myInstanceOfClassX;
    ...
}
Run Code Online (Sandbox Code Playgroud)

我应该把代码包装catch(exception &)好吗?如果我这样做,确实stringifstream保证有一个强有力的保证,没有资源泄露,没有任何东西被打开一半?

此外,如果我的类抛出myexception,这是从异常派生的,catch(exception &)似乎让它通过.那么让我看到catch(...)哪个IIRC可以访问违规行为?还有另外一种方法吗?

然后在某处有一条信息,不应该捕获在对象构造函数的子构造函数中抛出的任何异常,并且构造函数应该抛出以防任何成员对象抛出.

如果上面的代码不是从构造函数调用,而是从常规函数调用void foo(),我应该捕获哪些异常呢?outofmemory_something,filenotfound_something?我在哪里可以找到STL对象可以抛出的定义?它们的实施是否具体?

权威来源在哪里可以清除我对此主题的所有怀疑和疑问?

到目前为止,处理异常似乎就像在一大堆gooo中跳舞一样.错误代码似乎更简单,更安全......

Mar*_*ork 6

如果其中任何一个抛出

class X {
string m_str;
X() : m_str("foo")//what if this throws?
{
    ifstream b("a.in")//what if this throws?
}
Run Code Online (Sandbox Code Playgroud)

然后您创建的对象将不存在.
如果在对象的构造函数中抛出异常,则会破坏所有完全创建的成员(使用其析构函数),并将对象的内存返回给系统.因此,任何未在抛出点完全构造的构件都不会被销毁(因为它们尚未被创建).

  • 如果m_str()抛出初始化列表,那么该对象将永远不存在.
  • 如果ifstream抛入正文,则m_str将被销毁,并且该对象将永远不存在.

我应该将代码包装在catch(exception&)中吗?如果我这样做,字符串和ifstream是否保证有一个强有力的保证,没有资源泄露,什么都没有被打开一半?

即使您捕获异常(在对象外部)也没有对象可以工作,因为它从未存在(对象仅在构造函数完成后才开始其生命周期).

在上面,您可以保证没有泄漏或开放资源.

此外,如果我的类抛出myexception,即派生自异常,catch(exception&)似乎让它通过.所以这留下了我(II)捕获访问权限的catch(...)?还有另外一种方法吗?

如果您的异常是从std :: exception派生的,那么catch(std::exception&)它将起作用.如果它不起作用那么你做错了(但我们需要更多的细节(比如抛出的代码和捕获的代码,英文描述是不够的)).

然后在某处有一条信息,不应该捕获在对象构造函数的子构造函数中抛出的任何异常,并且构造函数应该抛出以防任何成员对象抛出.

可能是最好的选择,作为一般规则也不错的建议.

如果上面的代码不是从构造函数调用,而是从常规的函数void foo()调用,我应该捕获哪些异常呢?outofmemory_something,filenotfound_something?我在哪里可以找到STL对象可以抛出的定义?它们的实施是否具体?

如果你可以做一些事情,你应该只捕获例外.通常这没什么,所以不要抓住它们让应用程序正常退出(通过异常展开堆栈).

权威来源在哪里可以清除我对此主题的所有怀疑和疑问?

你的问题是如此多变以至于难以实现.
我可以推荐Herb Sutter的"Exceptional C++".

到目前为止,处理异常似乎就像在一大堆gooo中跳舞一样.错误代码似乎更简单,更安全......

你错了.例外情况要容易得多.你似乎只是过度思考它而感到困惑.这并不是说错误代码没有它们的位置.

如果出现问题,and you can not fix it locally则抛出异常.标准中的所有类都是在设计时考虑到例外并且行为正确.这样就离开了你的班级.

经验法则:(适用于您的对象)

  • 确保您的类在析构函数中清理自己
  • 如果您的对象包含资源,请确保遵守"3规则"
  • 每个对象永远不会有多个资源.
    注意:你可以有多个东西,比如std :: string或std :: ifstream,因为它们是控制资源的东西(它们各自控制一个资源,所以你的类不控制资源).资源(在此上下文中)是您必须手动创建/销毁的东西.

就是这样,其余的自动神奇地起作用.