Apakah saya perlu menutup ifstream secara manual?


201

Apakah saya perlu menelepon secara manual close()saat menggunakan std::ifstream?

Misalnya, dalam kode:

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");
}

Apakah saya perlu menelepon file.close()secara manual? Bukankah seharusnya ifstreammemanfaatkan RAII untuk menutup file?

Jawaban:


251

TIDAK

Ini adalah tujuan RAII, biarkan destructor melakukan tugasnya. Tidak ada salahnya menutupnya secara manual, tapi itu bukan cara C ++, ini pemrograman dalam C dengan kelas.

Jika Anda ingin menutup file sebelum akhir suatu fungsi, Anda selalu dapat menggunakan lingkup bersarang.

Dalam standar (27.8.1.5 Template kelas basic_ifstream), ifstreamakan diimplementasikan dengan basic_filebufanggota memegang pegangan file yang sebenarnya. Itu diadakan sebagai anggota sehingga ketika objek ifstream merusak, ia juga memanggil destruktor basic_filebuf. Dan dari standar (27.8.1.2), destruktor itu menutup file:

virtual ˜basic_filebuf();

Efek: Menghancurkan objek kelas basic_filebuf<charT,traits>. Panggilan close().


4
+1 Saya tidak tahu bahwa RAII menangani itu ... Saya kira Anda belajar sesuatu yang baru setiap hari
TStamper

21
Menggunakan lingkup bersarang hanya untuk menutup file benar-benar buatan - jika Anda bermaksud untuk menutupnya, panggil tutup () di atasnya.

3
Meskipun, Anda mungkin dapat berdebat bahwa membatasi masa hidup objek ke ruang lingkup yang diperlukan berarti Anda tidak akan secara tidak sengaja mengakses ifstream yang tertutup. Tapi itu agak dibuat-buat.
Eclipse

9
Dalam C ++ lingkup bersarang hampir tidak pernah tidak perlu. Mereka ada hubungannya dengan perilaku kode, terutama ketika ada sesuatu yang melempar. Jika pengelola masa depan menghapusnya, dia tidak tahu C ++ dengan sangat baik.
Elliot Cameron

2
Terkadang Anda perlu menelepon close()secara manual untuk penanganan kesalahan.
ks1322

71

Apakah Anda perlu menutup file?
TIDAK

Haruskah Anda menutup file?
Tergantung.

Apakah Anda peduli dengan kemungkinan kondisi kesalahan yang dapat terjadi jika file gagal ditutup dengan benar? Ingat bahwa panggilan dekat setstate(failbit)jika gagal. Destructor akan memanggil close()Anda secara otomatis karena RAII tetapi tidak akan meninggalkan Anda cara untuk menguji bit gagal karena objek tidak ada lagi.


14

Saya setuju dengan @Martin. Jika Anda menulis ke file, data mungkin masih berada di buffer dan mungkin tidak akan ditulis ke file sampai close()dipanggil. Tanpa melakukannya secara manual, Anda tidak tahu apakah ada kesalahan atau tidak. Tidak melaporkan kesalahan kepada pengguna adalah praktik yang sangat buruk.


5

Tidak, ini dilakukan secara otomatis oleh ifstreamdestructor. Satu-satunya alasan Anda harus memanggilnya secara manual, adalah karena fstreaminstance memiliki ruang lingkup yang besar, misalnya jika itu adalah variabel anggota dari instance long living class.


4
Alasan lain mungkin untuk memeriksa kesalahan penutupan file dan untuk mencegah melemparkan destruktor, jika pengecualian diizinkan dengan aliran.
Daniel Langr

4

Anda dapat mengizinkan destruktor untuk melakukan tugasnya. Tapi sama seperti objek RAII apa pun, ada kalanya menelepon secara manual dapat membuat perbedaan. Sebagai contoh:

#include <fstream>

using std::ofstream;

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

menulis konten file. Tapi:

#include <stdlib.h>

#include <fstream>

using std::ofstream;

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

tidak. Ini adalah kasus yang jarang terjadi ketika proses tiba-tiba keluar. Proses menabrak bisa melakukan hal serupa.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.