3

使用 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);
4

2 回答 2

1

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

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

于 2013-07-05T11:11:17.070 回答
0

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

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

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

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

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

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

于 2013-07-05T11:28:27.473 回答