这里的这种说法似乎不正确:
另一方面,双向文件流没有标志 隐式设置。这是因为双向流 不必在所有情况下都处于输入和输出模式。你 可能想要打开双向流以进行只读或写入 只。因此,双向文件流没有隐式输入或 输出模式。您必须始终设置双向文件流的打开 模式显式。
否则,此代码将无法编译。
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
fstream file("novo.txt", ios::out);
char i;
file >> i;
}
语句适用于 gcc
这里的这种说法似乎不正确:[...]
我不知道标准或Visual Studio,但我知道我正在使用的C++,这是来自GCC的那个。在那里,您可以查看相关的标题。
oistream::open
看起来像这样:
inline void
istream::open(const char* __s, ios_base::openmode __mode = ios_base::in) {
if (!_M_filebuf.open(__s, __mode | ios_base::in))
所以你这里有两件事:一个默认的函数参数,以防你在调用方法时没有指定一个,以及一个强制标志,它总是被或进入提供的模式。因此,无论您指定哪种模式,输入模式都将始终添加到您的规范中。其他代码,特别是构造函数,将委托给此代码。类似的情况也发生在ofstream::open
.另一方面,fstream::open
有默认参数,但没有强制参数:
inline void
fstream::open(const char* __s,
ios_base::openmode __mode = ios_base::in | ios_base::out) {
if (!_M_filebuf.open(__s, __mode))
因此,不传递任何模式都是可以的(至少在这个实现中,但请阅读@kmote的答案以获取更多详细信息),但是如果您确实传递了任何模式,那么您必须传递in
或out
或两者兼而有之,因为不会将强制模式添加到您指定的模式中(或未指定)。
这是我阅读 Apache 文档的方式,来源支持我的观点,至少对于我的实现而言。由于所有这些都在模板化代码中,因此您可以查看来自不同编译器的标头,以了解它如何处理这些情况。因此,请查看VS标头,查找basic_fstream
并查看其方法是如何实现的。
缺少编译器错误
否则,此代码将无法编译。
代码打开一个双向流仅用于输出,然后尝试从中输入内容。没有理由无法编译。流的静态类型是fstream
的,即双向的。只有在运行时,您才会将具有特定含义的某个标志传递给构造函数。编译器(通常)不会检查这一点,因此当代码无法实际从流中读取时,代码在运行时将行为异常。
请注意,我不确定 Windows 是否真的支持仅打开文件进行输出。操作系统支持的唯一文件模式很可能是只读和读写。(请注意,我只是在这里推测。在这种情况下,即使在运行时,打开文件仅用于输出并在之后读取也不会有问题,因为仅使用 out
打开文件或使用 in|out
打开文件没有区别。为了便于移植,应该选择正确的模式,因为那里有支持只写文件的内核。
虽然历史上对这个问题存在一些混淆,但我相信你引用的说法确实具有误导性,但不是因为你的例子中的原因。双向文件流确实隐式设置了标志,如文档中所述:
void open(
const char *_Filename,
ios_base::openmode _Mode = ios_base::in | ios_base::out,
int _Prot = (int)ios_base::_Openprot
);
基于 Apache 语句,我不希望您的代码示例失败,因为它明确将标志设置为 ::out。另一方面,我希望这段代码失败:
int main()
{
fstream file("novo.txt");
char i;
file >> i;
}
但是根据 MSDN 文档,这段代码也不会失败,文件将默认为 ios_base::in & out(因此,Apache 语句并不完全准确)。