【问题标题】:Is it correct to say that bidirectional file declarations do not set flags implicitly?说双向文件声明不隐式设置标志是否正确?
【发布时间】:2013-01-13 11:47:51
【问题描述】:

这句话here 似乎不正确:

另一方面,双向文件流没有标志 隐式设置。这是因为双向流 不必在所有情况下都处于输入和输出模式。你 可能想要打开一个双向流进行只读或写入 只要。因此双向文件流没有隐式输入或 输出模式。您必须始终设置双向文件流的打开 显式模式。

否则,此代码将无法编译。

#include <iostream>
#include <fstream>

using namespace std;

int main()
{
    fstream file("novo.txt", ios::out);
    char i;
    file >> i;
} 

【问题讨论】:

  • 我只是忽略了这一点,但是您使用的是什么编译器?一些编译器具有可以编译非法代码的“扩展”。

标签: c++ visual-studio-2010 stream fstream


【解决方案1】:

声明对于 gcc 是正确的

这里的陈述似乎不正确:[…]

我不了解标准或 Visual Studio,但我知道我正在使用的 C++,它来自 GCC。在那里你可以看看the relevant header

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))

所以你在这里有两件事:一个 default 函数参数,以防你在调用方法时没有指定一个,以及一个 forced 标志,它总是或-编辑到提供的模式。因此,无论您指定哪种模式,输入模式都将始终添加到您的规范中。其他代码,特别是构造函数,将委托给它。 ofstream::open 也会出现类似的情况。另一方面,fstream::opendefault 参数,但没有 forced 参数:

inline void
fstream::open(const char* __s,
              ios_base::openmode __mode = ios_base::in | ios_base::out) {
  if (!_M_filebuf.open(__s, __mode))

因此,不通过任何模式是可以的(至少在这个实现中,但请阅读@kmote 的答案以获取更多详细信息),但是如果你确实通过了任何模式, 那么您必须通过inout 或两者都通过,因为您指定(或未能指定)的模式不会添加强制模式。

这是我阅读 Apache 文档的方式,源代码支持我的观点,至少对于我的实现而言。由于所有这些都在模板化代码中,因此您可以查看来自不同编译器的标头以了解它如何处理这些情况。所以看看 VS 的头文件,寻找basic_fstream,看看它的方法是如何实现的。

缺少编译器错误

否则,此代码将无法编译。

您的代码打开一个双向流仅用于输出,然后尝试从中输入内容。这没有理由编译失败。流的静态类型为fstream,即双向。只有在运行时,您才会将具有特定含义的特定标志传递给构造函数。编译器(通常)不会对此进行检查,因此当您的代码无法从流中实际读取时,您的代码将因此在运行时出现异常。

请注意,我不确定 Windows 是否真的支持打开文件仅用于输出。 可能操作系统支持的唯一文件模式是只读和读写。 (请注意,我只是在这里推测。)在这种情况下,即使在运行时打开文件仅用于输出并随后从中读取也不会成为问题,因为仅使用 out 打开文件没有区别或in|out。为了可移植性,应该选择正确的模式,因为那里有支持只写文件的内核。

【讨论】:

  • 我同意你的看法。在这种情况下,编译器不应抱怨,因为 fstream 类具有运算符>>()。
【解决方案2】:

虽然有historically been some confusion regarding this matter,但我相信您引用的陈述确实具有误导性,但不是因为您的示例中的原因。双向文件流确实会隐式设置标志,如the documentation 中所述:

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 语句并不完全准确)。

【讨论】:

  • 您是如何得出结论的:“根据 Apache 声明,我不希望您的代码示例会失败,因为它明确将标志设置为 ::out ?”
  • 根据 Apache,“您必须始终明确设置双向文件流的打开模式”,这正是您通过包含 ios::out 参数所做的。
  • 但在这种情况下file &gt;&gt; i; 会失败。
猜你喜欢
  • 1970-01-01
  • 2015-03-10
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
  • 2023-03-14
  • 2013-03-13
  • 2012-05-30
相关资源
最近更新 更多