std :: unique_ptr dereference异常未在try-catch块中捕获

时间:2018-05-22 09:49:50

标签: c++ c++11 exception-handling unique-ptr

所以我想说:

struct test {
    bool a;
    int b;
};

int main()
{
    std::unique_ptr<test> ptr;
    // don't init the ptr

    try
    {
        if (!ptr->a)
        {
            std::cout << "ok" << std::endl;
        }
    }
    catch (const std::exception &ex)
    {
        std::cout << "ex: " << ex.what() << std::endl;
    }

    return 1;
}

所以在这里我设置了一个唯一的指针,但我没有初始化它(在更大的代码库中模拟它)但我想捕获异常。

问题是我的异常没有被调用 - 我只是遇到崩溃(内存访问错误)

我读了一些类似的问题(但不完全相同),这些问题表明我通过引用传递了异常 - 但这不起作用。

那么可以捕获unique_ptr去引用异常吗?

编辑:我应该补充一点,这是在Windows 7上运行MSVS2012可执行文件的盒子 - 这是相关的!

1 个答案:

答案 0 :(得分:4)

  

那么可以捕获unique_ptr去引用异常吗?

没有unique_ptr解除引用的例外情况。

作为documentation says

  
    

如果get() == nullptr

,则行为未定义   

您可以使用类似Java的行为轻松编写自己的智能指针,但这确实意味着在每个取消引用上支付测试和分支,这通常看起来很愚蠢。

对于评论中描述的略有不同的问题:

  

我有一个unique_ptr的列表 - 我试图通过在它周围放置一个try块来避免单独检查每个。

理智的解决方案可能是检查一次而不是每次后续解除引用:

if(any_of(begin(ptrs), end(ptrs), logical_not<unique_ptr<test>>{})
{
  throw MyNullPointerException();
}

根据后续评论,您只需在构造函数中添加一个check-and-throw包装器。

在C ++ 17中,您几乎可以获得所需的内容,而不是返回optional<unique_ptr<test>>(即,它包含一个已填充的unique_ptr,或者根本不包含任何东西:在这种情况下,调用{{ 1}}提取value会抛出unique_ptr,如果那里没有真的那么。​​)

如果您可以导入ot(或者没有C ++ 17),std::bad_optional_access可能会更好gsl::not_null<T>。例如,您可以将这些东西存储在容器中

using unique_not_null = std::unique_ptr<gsl::not_null<test>>;