C++ 在异常类中使用unique_ptr安全吗

C++ 在异常类中使用unique_ptr安全吗,c++,exception,smart-pointers,unique-ptr,C++,Exception,Smart Pointers,Unique Ptr,使用独特的ptr安全吗? 当我在析构函数中使用cout时,有时它会多次调用。-所以它会不断地复制。如果从一个对象复制两个副本,数据可能会丢失 #include <memory> class MyException { std::unique_ptr<Type> data; MyException(); ~MyException() {cout<<"test"<<endl;} MyException(MyExce

使用独特的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?
    }
}

正如你所发现的,你应该总是说
throw当您想重新抛出异常时,而不是
抛出ex。实际上,
抛出ex
将进行复制(如果
ex
是对基类的引用,则进行切片!)


因此,始终通过引用捕获,并且始终在不命名异常的情况下重新抛出。

对于gcc 4.7.3,您的示例无法编译,并抱怨MyException缺少副本构造函数。这是在它第一次抛出的行中,因此
throw MyException()
本身已经想要创建一个副本(至少在gcc中是这样)。另请参见和

要回答您关于在异常中使用指针是否是良好做法的问题,我通常会说不。除非要装载到异常上的数据非常大(这可能是一个设计问题),否则应该首选堆栈分配的数据结构。无论如何,在异常处理过程中,性能不应该是主要的考虑因素,所以复制周围的内容并不是一个真正的问题

如果你真的需要一个指针(也许
Type
没有复制构造函数,你不能改变它),使用
shared\u ptr
可以在紧要关头帮助你,尽管我觉得这是一个难看的破解。我可能会尝试将通过异常传递的信息减少到最低限度,以帮助调用方识别和处理问题

编辑:我在第15.1节第5段中找到了相关章节:

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


<> P>不使用复制构造函数,抛出异常对象实际上不是合法的C++。这是肯定的。但是,可能还有其他一些点未指明是否制作了副本。vs 2012。输出中带有“throw;”-1“test”。输出中带有“throw ex;”-2“test”。2析构函数=2对象…=>创建了副本。例如,我使用
共享\u ptr
在不同副本之间传递异常的调用堆栈。
std::exception_ptr ex =  std::current_exception();
std::rethrow_exception(ex);