使用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);
答案 0 :(得分:1)
正如您所发现的那样,当您想要重新抛出异常时,应始终说throw;
,而不是throw ex;
。实际上,throw ex;
将复制(并切片,如果ex
是对基类的引用!)。
所以,总是通过引用捕获,并且总是在不命名异常的情况下重新抛出。
答案 1 :(得分:0)
使用gcc 4.7.3,您的示例无法编译,抱怨MyException缺少复制构造函数。这是第一次抛出的行,因此throw MyException()
本身已经想要复制(至少在gcc中)。另请参阅this stackoverflow question和C++ FAQ。
要回答关于在异常中使用指针是否是好习惯的问题,我通常会说不。除非要捎带到异常上的数据很大(这可能是设计问题),否则应优先选择堆栈分配的数据结构。无论如何,性能不应该是异常处理中的主要问题,因此复制内容并不是一个真正的问题。
如果你真的需要一个指针(也许Type
没有复制构造函数且你无法改变它),使用shared_ptr
可以帮助你解决问题,虽然我觉得这会是一个丑陋的黑客。我可能会尝试将通过异常传递的信息减少到最低限度,以帮助调用者识别和处理问题。
编辑:我在C++ standard第15.1节第5段中找到了相关部分:
当抛出的对象是类对象时,即使复制/移动操作被省略,也应该可以访问复制/移动构造函数和析构函数。
因此,在没有复制构造函数的情况下抛出异常对象实际上不是合法的C ++。