ifstreamを手動で閉じる必要がありますか?


201

close()を使用する場合、手動で呼び出す必要がありstd::ifstreamますか?

たとえば、コードでは:

std::string readContentsOfFile(std::string fileName) {

  std::ifstream file(fileName.c_str());

  if (file.good()) {
      std::stringstream buffer;
      buffer << file.rdbuf();
      file.close();

      return buffer.str();
  }
  throw std::runtime_exception("file not found");
}

file.close()手動で呼び出す必要がありますか?ファイルを閉じるifstreamためにRAIIを使用すべきではありませんか?

回答:


251

番号

これがRAIIの目的です。デストラクタに任せてください。手動で閉じることに害はありませんが、C ++の方法ではなく、クラスを使用してCでプログラミングしています。

関数が終了する前にファイルを閉じたい場合は、いつでもネストされたスコープを使用できます。

標準(27.8.1.5クラステンプレートbasic_ifstream)では、実際のファイルハンドルを保持ifstreamするbasic_filebufメンバーを使用して実装されます。これはメンバーとして保持されているため、ifstreamオブジェクトが破壊されると、でデストラクタも呼び出されbasic_filebufます。そして、標準(27.8.1.2)から、そのデストラクタはファイルを閉じます。

virtual ˜basic_filebuf();

効果:クラスのオブジェクトを破棄しますbasic_filebuf<charT,traits>。を呼び出しますclose()


4
+1私はRAIIがそれを処理することを知りませんでした...私はあなたが毎日何か新しいことを学ぶと思います
TStamper

21
ファイルを閉じるためだけにネストされたスコープを使用することは完全に人為的です-ファイルを閉じるつもりなら、そのファイルに対してclose()を呼び出します。

3
ただし、オブジェクトの有効期間を必要なスコープに制限することで、閉じたifstreamに誤ってアクセスしないことを主張できる場合があります。しかし、それは少し工夫されています。
Eclipseの

9
C ++では、ネストされたスコープはほとんど不要です。特に何かがスローされたとき、それらはコードの動作と関係があります。将来のメンテナがそれらを削除した場合、彼はC ++をよく知りません。
Elliot Cameron

2
close()エラー処理のために手動で呼び出す必要がある場合があります。
ks1322

71

ファイルを閉じる必要がありますか?
番号

ファイルを閉じますか?
依存します。

ファイルが正しく閉じられなかった場合に発生する可能性のあるエラー状態を気にしますか?setstate(failbit)それが失敗した場合、そのclose呼び出しを覚えておいてください。デストラクタはclose()RAIIが原因で自動的に呼び出されますが、オブジェクトが存在しないため、フェイルビットをテストする方法はありません。


14

@Martinに同意します。ファイルに書き込む場合、データはまだバッファ上にあり、close()が呼び出されるまでファイルに書き込まれない可能性があります。手動で行わないと、エラーが発生したかどうかがわかりません。ユーザーにエラーを報告しないことは非常に悪い習慣です。


5

いいえ、これはifstreamデストラクタによって自動的に行われます。手動で呼び出す必要がある唯一の理由は、fstreamインスタンスが長いスコープを持つためです。たとえば、それが長いクラスのインスタンスのメンバー変数である場合などです。


4
もう1つの理由は、ストリームで例外が許可されている場合に、ファイルを閉じるエラーをチェックし、デストラクタがスローされないようにすることです。
Daniel Langr 2017

4

デストラクタにその仕事をさせることができます。しかし、他のRAIIオブジェクトと同じように、手動でcloseを呼び出すと違いが生じる場合があります。例えば:

#include <fstream>

using std::ofstream;

int main() {
  ofstream ofs("hello.txt");
  ofs << "Hello world\n";
  return 0;
}

ファイルの内容を書き込みます。だが:

#include <stdlib.h>

#include <fstream>

using std::ofstream;

int main() {
  ofstream ofs("hello.txt");
  ofs << "Hello world\n";
  exit(0);
}

しません。これらは、プロセスが突然終了するまれなケースです。クラッシュするプロセスも同様です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.