在Exception类中使用unique_ptr是否安全

时间:2013-07-05 09:45:38

标签: c++ exception smart-pointers unique-ptr

使用unique_ptr是否安全? 当我在析构函数中使用cout时,有时它会调用一次以上。 - 因此它可以随时复制。如果从一个对象获取两个副本 - 数据可能会丢失..

#include <memory>

class MyException
{
    std::unique_ptr<Type> data;

    MyException();
    ~MyException() {cout<<"test"<<endl;}

    MyException(MyException ex&);
};

int main()
{
    try
    {
        try
        {
            throw MyException();
        }
        catch (const MyException& ex)
        {
            throw;
            //or?
            throw ex; //will be copied?
        }
    return 0;
    }
    catch(const MyException/*& will be missed. will ex be copied?*/ ex)
    {
        throw; //wich ex will be re-throw, copy or original?
        //or?
        throw ex; //will be copied?
    }
}

我可以确定,重新投掷之间的数据不会丢失吗? 在异常中使用ptr从不同级别收集错误信息是否是一个很好的实践?

此外,MyException.data可能会在以下情况后丢失:

std::exception_ptr ex =  std::current_exception();
std::rethrow_exception(ex);

2 个答案:

答案 0 :(得分:1)

正如您所发现的那样,当您想要重新抛出异常时,应始终说throw;,而不是throw ex;。实际上,throw ex;将复制(并切片,如果ex是对基类的引用!)。

所以,总是通过引用捕获,并且总是在不命名异常的情况下重新抛出。

答案 1 :(得分:0)

使用gcc 4.7.3,您的示例无法编译,抱怨MyException缺少复制构造函数。这是第一次抛出的行,因此throw MyException()本身已经想要复制(至少在gcc中)。另请参阅this stackoverflow questionC++ FAQ

要回答关于在异常中使用指针是否是好习惯的问题,我通常会说不。除非要捎带到异常上的数据很大(这可能是设计问题),否则应优先选择堆栈分配的数据结构。无论如何,性能不应该是异常处理中的主要问题,因此复制内容并不是一个真正的问题。

如果你真的需要一个指针(也许Type没有复制构造函数且你无法改变它),使用shared_ptr可以帮助你解决问题,虽然我觉得这会是一个丑陋的黑客。我可能会尝试将通过异常传递的信息减少到最低限度,以帮助调用者识别和处理问题。

编辑:我在C++ standard第15.1节第5段中找到了相关部分:

  

当抛出的对象是类对象时,即使复制/移动操作被省略,也应该可以访问复制/移动构造函数和析构函数。

因此,在没有复制构造函数的情况下抛出异常对象实际上不是合法的C ++。