web-dev-qa-db-ja.com

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

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

たとえば、コードでは:

_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 [〜#〜] を使用すべきではありませんか?

179

番号

これが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()を呼び出します。

232
Eclipse

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

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

ファイルが正しく閉じられなかった場合に発生する可能性のあるエラー状態を気にしますか?失敗した場合、closeはsetstate(failbit)を呼び出すことに注意してください。 [〜#〜] raii [〜#〜]のため、デストラクタはclose()を自動的に呼び出しますが、オブジェクトとして失敗ビットをテストする方法を残しません長く存在します。

62
Martin York

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

12
Mark Edwards

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

6
Dimitri C.

デストラクタに仕事をさせることができます。ただし、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);
}

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

4
ericcurtin