1

ここでのこのステートメントは正しくないようです。

一方、双方向ファイル ストリームには、フラグが暗黙的に設定されていません。これは、双方向ストリームがすべての場合に入力モードと出力モードの両方である必要がないためです。読み取り専用または書き込み専用の双方向ストリームを開きたい場合があります。したがって、双方向ファイル ストリームには、暗黙的な入力モードまたは出力モードはありません。双方向ファイル ストリームのオープン モードは常に明示的に設定する必要があります。

そうしないと、このコードはコンパイルされません。

#include <iostream>
#include <fstream>

using namespace std;

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

2 に答える 2

2

ステートメントは 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))

したがって、ここには 2 つのものがあります。メソッドを呼び出すときに指定しなかった場合のデフォルトの関数引数と、提供されたモードに常に or-ed される強制フラグです。したがって、どのモードを指定しても、入力モードは常に仕様に追加されます。他のコード、特にコンストラクターはこれに委譲します。と同様の状況が発生し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 の回答をお読みください)。ただし、モードを渡す場合は、いずれまたは両方を渡す必要があります。指定した (または指定しなかった) モードに強制モードが追加されることはないためです。inout

これは私が Apache のドキュメントを読む方法であり、少なくとも私の実装では、ソースは私の見解をサポートしています。これらはすべてテンプレート化されたコードであるため、別のコンパイラのヘッダーを調べて、これらの状況をどのように処理するかを確認できます。VSヘッダーを見て、basic_fstreamそのメソッドがどのように実装されているかを探して確認してください。

コンパイラ エラーの欠如

そうしないと、このコードはコンパイルされません。

コードは出力専用の双方向ストリームを開き、そこから入力を試みます。これがコンパイルに失敗する理由はありません。ストリームの静的タイプはfstream、つまり双方向です。実行時にのみ、特定の意味を持つ特定のフラグをコンストラクターに渡します。コンパイラは(通常)それをチェックしないため、実際にストリームからの読み取りに失敗すると、コードは実行時に誤動作します。

Windows が実際に出力専用のファイルを開くことをサポートしているかどうかはわかりません。OS でサポートされているファイル モードは、読み取り専用と読み書きのみである可能性があります。out(ここでは推測しているだけであることに注意してください。)その場合、出力のみのためにファイルを開き、後でそれから読み取ることは、実行時でも問題にはなりませんin|out。書き込み専用ファイルをサポートするカーネルが存在するため、移植性のために正しいモードを選択する必要があります。

于 2013-01-29T22:17:18.690 に答える
1

この問題に関して歴史的に混乱がありましたが、あなたが引用した声明は確かに誤解を招くと思いますが、あなたの例の理由によるものではありません. ドキュメントに記載されているように、双方向ファイル ストリームは暗黙的にフラグを設定します。

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 ステートメントは完全に正確ではありません)。

于 2013-01-29T21:28:32.467 に答える