代码之家  ›  专栏  ›  技术社区  ›  wilhelmtell

当RAII对象无法构造

  •  5
  • wilhelmtell  · 技术社区  · 14 年前

    try {
        std::vector<int> v(LOTS);
        // try scope ends here because that's what the catch is for
    } catch( const std::bad_alloc& ) {
        // ...
    }
    // v? what v?
    

    授予,的默认构造函数 std::vector 不会扔,这会有帮助,但这不是一般情况。构造函数很可能抛出。如果我想处理任何资源获取失败,如果仍然可以继续,我该如何处理 扔?

    :要澄清的是,我的问题是,如果资源无法获取,则可能需要重试,以此类推。也许我可以试着找一个替代资源。

    4 回复  |  直到 14 年前
        1
  •  7
  •   Steve Jessop    14 年前

    取决于你所说的“继续”。无论什么操作需要资源都会失败:这就是“需要”的意思。因此,当您希望在出现错误后继续时,可能会编写如下代码:

    void something_using_RAII(thingummy &t) {
        vector<int> v(t.size_required);
        // do something using v
    }
    
    ...
    
    for each thingummy {
        try {
             something_using_RAII(this_thingummy);
        } catch(const std::bad_alloc &) {
             std::cerr << "can't manage that one, sorry\n";
        }
    }
    

    这就是为什么只有在有值得做的事情时才应该捕捉异常(在本例中,报告失败并继续下一个Thingym)。

    如果要在失败时重试,但仅当构造函数失败时,而不是其他任何失败时:

    while(not bored of trying) {
        bool constructor_failed = true;
        try {
            vector<int> v(LOTS);
            constructor_failed = false;
            // use v
        } catch(...) {
            if (!constructor_failed) throw;
        }
    }
    

    这或多或少是 std::new_handler 工作-处理程序在类似循环的catch子句中调用,但不需要标志。

    如果要在失败时尝试其他资源:

    try {
        vector<int> v(LOTS);
        // use v
    } catch(...) try {
        otherthing<int> w(LOTS);
        // use w
    } catch(...) {
        // failed
    }
    

    如果“use v”和“use w”基本上是相同的代码,那么重构成一个函数并从两个地方调用它。你的职能在这一点上做了很多工作。

        2
  •  7
  •   Johannes Schaub - litb    14 年前

    如果RAII构造函数抛出,则在抛出点之前绑定到RAII对象的所有资源都将被正确清理。C++规则是合理设计的,以保证。

    如果你的 v 因为一个 bad_alloc try

    所以如果你因此使用RAII,你不需要手册 尝试 catch 就像那样,因为RAII对象为您处理清理。如果你 出于某种原因需要它,在上面的情况下,您可以像下面这样使用swap。

    std::vector<int> v;
    try {
        std::vector<int> vtry(LOTS);
        v.swap(vtry); // no-throw
    } catch( const std::bad_alloc& ) {
        // ...
    }
    // v!
    
        3
  •  2
  •   sth ACP    14 年前

    v 无法创建,所有试图使用的代码 catch 在代码使用的代码之后 ,如果没有

        4
  •  0
  •   Benjamin Lindley    14 年前

    所有使用v的代码都需要在try块中。如果问题是如何缩小引发异常的代码的范围,则可以使用某种标志来指示您在try块中的位置,如下所示:

    string flag;
    try
    {
        flag = "creating vector<int> v";
        std::vector<int> v(LOTS);
    
        flag = "performing blaggity bloop";
        blaggity_bloop();
    
        flag = "doing some other stuff";
        some_other_stuff();
    }
    catch( const std::bad_alloc& )
    {
        cerr << "Bad allocation while " << flag << endl;
    }