क्या मुझे मैन्युअल रूप से एक 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()मैन्युअल रूप से कॉल करने की आवश्यकता है ? फ़ाइलों को बंद करने के लिए RAII काifstream उपयोग नहीं करना चाहिए ?

जवाबों:


251

नहीं

यह RAII के लिए है, विध्वंसक को अपना काम करने दें। इसे मैन्युअल रूप से बंद करने में कोई बुराई नहीं है, लेकिन यह सी ++ तरीका नहीं है, यह सी के साथ कक्षाओं में प्रोग्रामिंग कर रहा है।

यदि आप किसी फ़ंक्शन के अंत से पहले फ़ाइल को बंद करना चाहते हैं तो आप हमेशा नेस्टेड स्कोप का उपयोग कर सकते हैं।

मानक (27.8.1.5 क्लास टेम्पलेट basic_ifstream) में, वास्तविक फ़ाइल हैंडल रखने वाले सदस्य के ifstreamसाथ लागू किया जाना basic_filebufहै। इसे एक सदस्य के रूप में रखा जाता है ताकि जब कोई इफस्ट्रीम ऑब्जेक्ट नष्ट हो जाए, तो इसे विध्वंसक भी कहा जाता है basic_filebuf। और मानक (27.8.1.2) से, वह विध्वंसक फ़ाइल बंद कर देता है:

virtual ˜basic_filebuf();

प्रभाव: कक्षा की एक वस्तु को नष्ट कर देता है basic_filebuf<charT,traits>। कहता है close()


4
+1 मैं नहीं जानता था कि RAII हैंडल करता है ... मुझे लगता है कि आप हर रोज़ कुछ नया सीखते हैं
TStamper

21
फ़ाइल को बंद करने के लिए केवल एक नेस्टेड स्कोप का उपयोग करना पूरी तरह से कृत्रिम है - यदि आपको इसे बंद करने का मतलब है, तो उस पर कॉल () बंद करें।

3
हालाँकि, आप यह तर्क देने में सक्षम हो सकते हैं कि ऑब्जेक्ट के जीवनकाल को आवश्यक दायरे तक सीमित रखने का मतलब है कि आप गलती से एक बंद इफस्ट्रीम तक नहीं पहुंच पाएंगे। लेकिन वह थोड़ा सा वंचित है।
ग्रहण

9
C ++ में नेस्टेड स्कोप लगभग कभी भी अनावश्यक नहीं होते हैं। उनके पास कोड के व्यवहार के साथ सब कुछ है, खासकर जब कुछ फेंकता है। अगर एक भविष्य का अनुचर उन्हें हटा देता है, तो वह C ++ को अच्छी तरह से नहीं जानता है।
इलियट कैमरन

2
कभी-कभी आपको close()त्रुटि हैंडलिंग के लिए मैन्युअल रूप से कॉल करने की आवश्यकता होती है ।
ks1322

71

क्या आपको फ़ाइल बंद करने की आवश्यकता है?
नहीं

क्या आपको फ़ाइल बंद करनी चाहिए?
निर्भर करता है।

क्या आप संभावित त्रुटि स्थितियों के बारे में परवाह करते हैं जो फ़ाइल के सही ढंग से बंद होने में विफल हो सकती हैं? याद रखें कि setstate(failbit)यदि यह विफल रहता है तो करीबी कॉल करें । विध्वंसक आरएआई केclose() कारण स्वचालित रूप से आपके लिए कॉल करेगा, लेकिन आपको असफल बिट के परीक्षण का एक तरीका नहीं छोड़ेगा क्योंकि ऑब्जेक्ट अब मौजूद नहीं है।


14

मैं @Martin से सहमत हूं। यदि आप फ़ाइल को लिखते हैं, तो डेटा अभी भी एक बफर पर बैठा हो सकता है और जब तक close()कॉल नहीं किया जाता है तब तक फ़ाइल को नहीं लिखा जा सकता है। इसे मैन्युअल रूप से करने के बिना, आपको पता नहीं है कि कोई त्रुटि थी या नहीं। एक उपयोगकर्ता के लिए त्रुटियों की रिपोर्ट नहीं करना एक बहुत बुरा अभ्यास है।


5

नहीं, यह ifstreamविध्वंसक द्वारा स्वचालित रूप से किया जाता है । एकमात्र कारण आपको इसे मैन्युअल रूप से कॉल करना चाहिए, क्योंकि fstreamउदाहरण के लिए एक बड़ा स्कोप है, उदाहरण के लिए अगर यह एक लंबे समय तक रहने वाले वर्ग उदाहरण का सदस्य चर है।


4
एक अन्य कारण फ़ाइल-क्लोज़िंग त्रुटियों की जांच करना और विध्वंसक फेंकने से रोकने के लिए हो सकता है, अगर धारा के साथ अपवादों की अनुमति है।
डैनियल लैंगर

4

आप विध्वंसक को यह काम करने की अनुमति दे सकते हैं। लेकिन किसी भी RAII ऑब्जेक्ट की तरह ही कई बार ऐसा हो सकता है कि मैन्युअल रूप से कॉल करने से फर्क पड़ सकता है। उदाहरण के लिए:

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

ऐसा नहीं करता। ये दुर्लभ मामले हैं जहां एक प्रक्रिया अचानक निकल जाती है। क्रैश प्रक्रिया समान हो सकती है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.