C++-关于fstream析构的问题

C++-关于fstream析构的问题

瑾兮 发布于 2017-06-03 字数 198 浏览 1582 回复 5

最近看Effective c++ , 上面说 使用类来管理资源, 现在想到一个问题: fstream打开一个文件后, 如果忘记了关闭, 会不会在析构的时候自动关闭文件? google了一下, 有的说会, 有的说不会, 谁能给个官方的回答?

如果你对这篇文章有疑问,欢迎到本站 社区 发帖提问或使用手Q扫描下方二维码加群参与讨论,获取更多帮助。

扫码加入群聊

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

泛泛之交 2017-08-29 5 楼

确定地说,会。解释如下:

fstream 是basic_fstream<char, char_traits<char>>的typedef。

在C++标准ISO/IEC 14882:2011的 37.9.1.14节,要求basic_fstream有成员变量:

basic_filebuf<charT,traits> sb; // exposition only

标准中没有明确列出basic_fstream的析构函数,意味着将使用默认的析构函数,其行为将在析构中调用成员变量sb的析构。

而basic_filebuf的规范在27.9.12节[filebuf.cons],条款5:

virtual ~basic_filebuf();
5 *Effects*: Destroys an object of class basic_filebuf<charT,traits>. Calls close(). If an exception
occurs during the destruction of the object, including the call to close(), the exception is caught but
not rethrown (see 17.6.5.12).

明确要求basic_filebuf的析构必须调用close,且不得泄露异常。

综合上述条款,basic_fstream默认生成的析构函数将通过调用basic_filebuf的析构,从而间接调用close方法。即,会在析构中自动关闭文件。

事实上,各种常见编译器,VC,g++,Clang,无一例外,其实现都符合标准。

晚风撩人 2017-08-24 4 楼

会自动关闭,但是关闭的地方是析构的地方。有的时候析构之前就会想要关掉这个文件了,那就得手工关。

泛泛之交 2017-08-03 3 楼

像fopen 如果不用fcolse关闭 文件是无法真正修改的
但是貌似这样的问题不会发生在c++的fstream类身上
可以直接查看 fstream源码中的析构部分

 basic_fstream类
virtual __CLR_OR_THIS_CALL ~basic_fstream()
{ // destroy the object
}

virtual __CLR_OR_THIS_CALL ~basic_ifstream()
{ // destroy the object
}
virtual __CLR_OR_THIS_CALL ~basic_ofstream()
{ // destroy the object
}

看下面的类

 basic_filebuf类
virtual __CLR_OR_THIS_CALL ~basic_filebuf()
{ // destroy the object
if (_Myfile != 0)
_Reset_back(); // revert from _Mychar buffer
if (_Closef)
close();
}

这是buf类 显然是他完成了文件关闭

再看为什么他关闭 显然 basic_fstream的构造函数在初始化对象的时候也是用他打开的

 explicit basic_ofstream(const char *_Filename,
ios_base::openmode _Mode = ios_base::out,
int _Prot = (int)ios_base::_Openprot)
: _Mybase(&_Filebuffer)
{ // construct with named file and specified mode
if (_Filebuffer.open(_Filename, _Mode | ios_base::out, _Prot) == 0)
_Myios::setstate(ios_base::failbit);
}

在析构的时候 虽然 类本身的析构函数没有关闭文件 但是 已经由辅助类帮助完成了 !

所以 可以看出 就算不手动关闭 fstream对象打开的文件 在析构的时候也会自动完成关闭!!

偏爱自由 2017-07-26 2 楼

答案应该是:没有必要手动关闭fstream。在析构的时候会自动关闭的。
fstream实现了RAII,会在作用域末尾自动关闭。

拿ifstream来说,依据《C++ Standard》27.8.1.5:
basic_ifstream:

namespace std {
template < class charT , class traits = char_traits <charT > >
class basic_ifstream : public basic_istream <charT ,traits > {
public :
typedef charT char_type ;
typedef typename traits :: int_type int_type ;
typedef typename traits :: pos_type pos_type ;
typedef typename traits :: off_type off_type ;
typedef traits traits_type ;
/ / 27.8.1.6 Constructors:
basic_ifstream ();
explicit basic_ifstream ( const char * s ,
ios_base :: openmode mode = ios_base :: in );
/ / 27.8.1.7 Members:
basic_filebuf <charT , traits >* rdbuf () const ;
bool is_open () const ;
void open ( const char * s , ios_base :: openmode mode = ios_base :: in );
void close ();
private :
/ / basic_filebuf<charT,traits> sb;
};
}

它有一个basic_filebuf成员,记录了文件的句柄。而
basic_filebuf的析构函数:

virtual ~ basic_filebuf ();
3 Effects: Destroys an object of class basic_filebuf<charT,traits>. Calls close().

但是如果你想要进行错误检测的话,最好还是手动关闭。因为虽然自动析构会自动关闭,但是这个时候对象已不存在,无法进行错误检测。

很好的参考资料:
需要手动关闭stream吗

而且,你看《C++ primer》第三版的第870页,上面的例子程序就没有去手动关闭fstream。

灵芸 2017-07-17 1 楼

既然C++都说要使用类来管理资源,那么一般都会使用RAII机制,这是C++封装的最高层次。