我有一些看起来有点像这样的代码:
void writeToStream( std::ostream & outputStream )
{
MyXmlWriter xmlWriter{ outputStream };
xmlWriter.addNode();
xmlWriter.addNode();
xmlWriter.close(); // should this be called in `MyXmlWriter` destructor?
}
close函数会写一些xml关闭标记,以便正确解析文件。构造函数编写xml文件的标头。可以考虑xmlWriter.close();
清理代码。 C ++的常见建议是将清理代码放入析构函数中。这样你就永远不会忘记清理干净。但是,在我们的例子中,清理代码可能会抛出。 (想象一下,file
可以启用异常,对文件的写入可能会失败。)因此,如果在析构函数中调用close()
函数,那么它应该包含在try-catch块中抛出所有异常:
MyXmlWriter::~MyXmlWriter()
{
try
{
close();
}
catch (...)
{
}
}
但是,在这种情况下,不会通知来电者任何错误。函数writeToStream()
可能无法将关闭的xml标记写入文件,而调用者不知道它。在这种情况下,最佳做法是什么?
答案 0 :(得分:5)
吞咽异常通常是“最糟糕的做法”,因为它违背了首先投掷的目的。
但是在这种情况下,你真的只想要在析构函数中使用一部分功能,不包括刷新,这是一个“奖励”但是有可能抛出。尝试冲洗可能仍然存在副作用,例如不必要地等待已经发生的网络超时。
正如James Kanze所提到的,最佳做法是在析构函数运行之前手动刷新,这排除了析构函数中的异常情况。
将来C ++可能会更好地支持事务。但就目前而言,您的方法是合理的。在任何情况下,它都是指定std::filebuf
的析构函数的工作方式:
效果:销毁类
basic_filebuf<charT,traits>
的对象。致电close()
。如果在销毁对象期间发生异常,包括对close()
的调用,则会捕获异常但不会重新抛出异常(参见17.6.5.12)。
答案 1 :(得分:4)
你在结束什么?通常,必须在销毁之前关闭打开以进行写入的文件(std::ostream
,FILE*
或系统相关文件描述符),以便在完成关闭后检查错误并报告它们。但是,有一些例外,特别是包装一个打开文件的类通常应该在它们的析构函数中关闭它(不检查错误,因为你无法对它们做任何事情),以确保在它的情况下进行适当的清理。例外。
据推测,关闭前的异常意味着已经存在错误,并且不会使用正在写入的文件。我通常将输出包装在具有commit
函数的类中。 commit
关闭,并检查错误。如果在commit
之前调用析构函数,它会关闭,而不检查错误,然后删除正在写入的文件,因为它可能不完整或不可用。