Bir ifstream'i manuel olarak kapatmam gerekir mi?


201

Ben manuel çağrı gerekiyor mu close()ben kullandığınızda std::ifstream?

Örneğin, kodda:

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()Manuel olarak aramam gerekir mi? Olmamalı ifstreamfaydalanmak de ray dosyaları kapatmak için?

Yanıtlar:


252

HAYIR

RAII bunun içindir, yıkıcı işini yapsın. Elle kapatmanın bir zararı yoktur, ancak C ++ yolu değildir, C ile sınıflarla programlama yapar.

Dosyayı bir işlevin sonundan önce kapatmak istiyorsanız, her zaman iç içe geçmiş bir kapsam kullanabilirsiniz.

Standartta (27.8.1.5 Sınıf şablonu basic_ifstream), gerçek dosya tanıtıcısına ifstreamsahip bir basic_filebufüye ile uygulanacaktır . Üye olarak tutulur, böylece bir ifstream nesnesi yok edildiğinde, yıkıcıyı da çağırır basic_filebuf. Ve standarttan (27.8.1.2), bu yıkıcı dosyayı kapatır:

virtual ˜basic_filebuf();

Efektler: Sınıf nesnesini yok eder basic_filebuf<charT,traits>. Aramalar close().


4
+1 RAII'nin bununla başa çıktığını bilmiyordum ... Sanırım her gün yeni bir şeyler öğreniyorsun
TStamper

22
Yalnızca dosyayı kapatmak için iç içe bir kapsam kullanmak tamamen yapaydır - kapatmak istiyorsanız, üzerine close () çağırın.

3
Bununla birlikte, nesnenin ömrünü gerekli kapsamla sınırlamanın, yanlışlıkla kapalı bir akışa erişemeyeceğiniz anlamına gelebileceğini iddia edebilirsiniz. Ama bu biraz çelişkili.
Tutulma

9
C ++ 'da içiçe olan kapsamlar neredeyse hiç gereksiz değildir. Kodun davranışı ile ilgili her şeyleri var, özellikle bir şey atıldığında. Gelecekteki bir bakıcı onları kaldırırsa, C ++ 'ı çok iyi bilmez.
Elliot Cameron

2
Bazen close()hataların giderilmesi için manuel olarak aramanız gerekebilir .
ks1322

71

Dosyayı kapatmanız mı gerekiyor?
HAYIR

Dosyayı kapatmalı mısınız?
Bağlı olmak.

Dosya doğru kapanmazsa oluşabilecek olası hata durumlarını önemsiyor musunuz? setstate(failbit)Başarısız olursa yakın aramaları unutmayın . Yıkıcı RAIIclose() nedeniyle sizi otomatik olarak arayacak , ancak nesne artık mevcut olmadığından başarısız biti test etmenin bir yolunu bırakmayacaktır.


14

@Martin'e katılıyorum. Dosyaya yazarsanız, veriler yine de bir arabellekte oturuyor olabilir ve close()çağrılana kadar dosyaya yazılamayabilir . Manuel olarak yapmadan, bir hata olup olmadığı hakkında hiçbir fikriniz yoktur. Hataları bir kullanıcıya bildirmemek çok kötü bir uygulamadır.


5

Hayır, bu ifstreamyıkıcı tarafından otomatik olarak yapılır . Manuel olarak çağırmanızın tek nedeni fstream, örneğin uzun bir yaşam sınıfı örneğinin üye değişkeni olması durumunda örneğin büyük bir kapsamı olmasıdır.


4
Başka bir neden, dosya kapanma hatalarını kontrol etmek ve akışta istisnalara izin veriliyorsa yıkıcı fırlatmayı önlemek olabilir.
Daniel Langr

4

Yıkıcının işini yapmasına izin verebilirsiniz. Ancak herhangi bir RAII nesnesinde olduğu gibi, manuel olarak kapatmanın çağrılmasının bir fark yaratabileceği zamanlar olabilir. Örneğin:

#include <fstream>

using std::ofstream;

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

dosya içeriğini yazar. Fakat:

#include <stdlib.h>

#include <fstream>

using std::ofstream;

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

yapmaz. Bunlar, bir sürecin aniden çıktığı nadir durumlardır. Çökme süreci de benzer olabilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.