我应该把文件的末尾写在析构函数中吗
Should I write the end of the file in the destructor?
我有一些代码看起来有点像这样:
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标记写入文件。在这种情况下,最佳做法是什么?
吞下异常通常是"最糟糕的做法",因为它一开始就违背了抛出的目的。
但在这种情况下,您实际上只需要析构函数中的一个子集,而不包括刷新,这是一种"奖励",但可能会引发抛出。尝试刷新可能仍然会有副作用,例如不必要地等待已经发生的网络超时。
正如James Kanze所提到的,最佳实践是在析构函数运行之前手动刷新,这排除了析构函数中的异常情况。
在未来,C++可能会更好地支持事务。但就目前而言,你的做法是合理的。在任何情况下,这就是指定std::filebuf
的析构函数的工作方式:
效果:销毁
basic_filebuf<charT,traits>
类的对象。调用close()
。如果在对象销毁过程中发生异常,包括对close()
的调用,则会捕获该异常,但不会重新抛出(见17.6.5.12)
你要结束什么?通常,必须在销毁之前关闭打开进行写入的文件(std::ostream
、FILE*
或系统相关的文件描述符),以便在关闭后检查错误并报告错误。然而,也有例外,特别是包装打开文件的类通常应该在其析构函数中关闭该文件(不检查错误,因为您对此无能为力),以确保在出现异常时进行正确的清理。
据推测,关闭前出现异常意味着已经出现错误,并且将不会使用正在写入的文件。我通常使用commit
函数将输出封装在类中。commit
关闭并检查错误。如果在commit
之前调用析构函数,它将关闭,而不检查错误,然后删除正在写入的文件,因为它可能不完整或不可用。
- 什么时候调用组成单元对象的析构函数
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 内联映射初始化的动态atexit析构函数崩溃
- 什么时候调用析构函数
- 优先顺序:智能指针和类析构函数
- C++-明确何时以及如何调用析构函数
- 使用基类指针创建对象时,缺少派生类析构函数
- 在c++中使用向量时,如何调用构造函数和析构函数
- 重载运算符new[]的行为取决于析构函数
- 我需要知道编译器如何在cpp中使用析构函数
- 为什么在使用转换构造函数赋值后调用C++类的析构函数?
- 如何正确定义C++类析构函数并将其链接到主文件?
- 文件流析构函数是否可以在C++中引发异常?
- 我应该把文件的末尾写在析构函数中吗
- 调用remove()删除析构函数中的文件是否安全
- C++头文件中的空接口析构函数
- 当在头文件上而不是在CPP文件上实现时,析构函数会导致内存泄漏——仅在linux上实现
- cpp文件中的内联构造函数和析构函数
- 为什么类的析构函数"inlined"在仅包含类的头文件的 cpp 中
- 在析构函数中调用CloseHandle会导致运行时内存错误,即如何正确关闭结构/类中的文件句柄