2012-12-31 15 views
46

क्या कोई व्यक्ति कृपया व्याख्या कर सकता है (अधिमानतः सादे अंग्रेजी का उपयोग कर) कैसे std::flush काम करता है?std :: फ्लश कैसे काम करता है?

  • यह क्या है?
  • आप एक स्ट्रीम फ्लश कब करेंगे?
  • यह क्यों महत्वपूर्ण है?

धन्यवाद।

उत्तर

74

चूंकि इसका उत्तर उत्तर नहीं दिया गया थाstd::flush होता है, यहां वास्तव में यह कुछ विवरण है। std::flush एक मैनिपुलेटर है, यानी, एक विशिष्ट हस्ताक्षर वाला एक फ़ंक्शन है।सरल शुरू करने के लिए, आप हस्ताक्षर

std::ostream& std::flush(std::ostream&); 

होने के std::flush के बारे में सोच सकता है, हालांकि (यदि आप रुचि रखते हैं, यह नीचे के रूप में अच्छी तरह से समझाया गया है) वास्तविकता, थोड़ा अधिक जटिल है।

धारा वर्ग ओवरलोड आउटपुट ऑपरेटर इस फ़ॉर्म के ऑपरेटरों को लेते हैं, यानी, एक सदस्य फ़ंक्शन एक मैनिपुलेटर को तर्क के रूप में लेता है।

std::ostream& std::ostream::operator<< (std::ostream& (*manip)(std::ostream&)) { 
    (*manip)(*this); 
    return *this; 
} 

है यही कारण है कि, जब आप "उत्पादन" std::flush एक std::ostream के साथ, यह सिर्फ इसी समारोह, यानी कहता है, निम्नलिखित दो बयान के बराबर हैं:

उत्पादन ऑपरेटर वस्तु के साथ ही जोड़तोड़ कॉल
std::cout << std::flush; 
std::flush(std::cout); 

अब, std::flush() ही काफी सरल है:

std::ostream& std::flush(std::ostream& out) { 
    out.flush(); 
    return out; 
} 
: सभी यह होता है std::ostream::flush() कॉल करने के लिए, यानी, आप इसके कार्यान्वयन की कल्पना कर सकते हैं कुछ इस तरह देखने के लिए है

std::ostream::flush() फ़ंक्शन तकनीकी रूप से स्ट्रीम बफर (यदि कोई है) पर स्ट्रीम बफर (यदि कोई है) पर std::streambuf::pubsync() पर कॉल करता है: स्ट्रीम बफर वर्णों को बफर करने और बाहरी गंतव्य पर वर्ण भेजने के लिए ज़िम्मेदार होता है जब प्रयुक्त बफर ओवरफ़्लो हो जाता है या जब आंतरिक प्रतिनिधित्व होता है बाहरी गंतव्य के साथ समन्वयित किया जाना चाहिए, यानी, जब डेटा फ़्लश किया जाना चाहिए। बाहरी गंतव्य के साथ समन्वयित अनुक्रमिक धारा पर इसका मतलब है कि किसी भी बफर किए गए वर्ण तुरंत भेजे जाते हैं। यही है, std::flush का उपयोग करके स्ट्रीम बफर अपने आउटपुट बफर को फ्लश करने का कारण बनता है। उदाहरण के लिए, जब कंसोल फ्लशिंग पर डेटा लिखा जाता है तो कंसोल पर इस बिंदु पर अक्षर दिखाई देते हैं।

यह सवाल उठा सकता है: वर्ण तुरंत क्यों नहीं लिखे गए हैं? सरल जवाब यह है कि लेखन अक्षर आमतौर पर काफी धीमी होती है। हालांकि, उचित मात्रा में वर्ण लिखने में कितना समय लगता है, वह अनिवार्य रूप से केवल एक ही लिखने के समान है। वर्णों की मात्रा ऑपरेटिंग सिस्टम, फाइल सिस्टम इत्यादि की कई विशेषताओं पर निर्भर करती है, लेकिन अक्सर 4k वर्णों की तरह कुछ ही समय में केवल एक वर्ण के रूप में लिखा जाता है। इस प्रकार, बाहरी गंतव्य के विवरण के आधार पर उन्हें बफर का उपयोग करके भेजने से पहले वर्णों को बफर करना एक बड़ा प्रदर्शन सुधार हो सकता है।

उपर्युक्त तीन में से दो प्रश्नों का उत्तर देना चाहिए। शेष प्रश्न यह है कि आप एक धारा कब फ्लश करेंगे? जवाब यह है: जब पात्रों को बाहरी गंतव्य पर लिखा जाना चाहिए! यह (, बंद करने के लिए एक फ़ाइल परोक्ष बफर flushes हालांकि) एक फ़ाइल लेखन के अंत में हो सकता है या तुरंत (ध्यान दें कि std::cout स्वचालित रूप से प्लावित है जब std::cout रूप std::cin से पढ़ है std::istream::tie() 'std::cin करने d) उपयोगकर्ता इनपुट के लिए पूछ रहा से पहले। यद्यपि ऐसे कुछ अवसर हो सकते हैं जहां आप स्पष्ट रूप से स्ट्रीम को फ़्लश करना चाहते हैं, लेकिन मुझे लगता है कि वे काफी दुर्लभ हैं।

अंत में, मैं क्या std::flush वास्तव में है की पूरी तस्वीर देने का वचन दिया: धाराओं वर्ग (विभिन्न चरित्र प्रकार के साथ काम कर अभ्यास वे char और wchar_t के साथ काम करने में सक्षम में टेम्पलेट्स हैं, उन्हें किसी अन्य पात्रों के साथ काम कर रही है काफी शामिल है हालांकि यदि आप वास्तव में निर्धारित हैं तो करने योग्य)।धाराओं के सभी instantiations साथ std::flush उपयोग करने में सक्षम होने के लिए, वह इस तरह का हस्ताक्षर के साथ एक समारोह टेम्पलेट होता है:

template <typename cT, typename Traits> 
std::basic_ostream<cT, Traits>& std::flush(std::basic_ostream<cT, Traits>&); 

जब std::flush तुरंत का उपयोग कर std::basic_ostream के इन्स्टेन्शियशन साथ यह नहीं वास्तव में बात करता है: संकलक टेम्पलेट तर्क स्वचालित रूप से deduces। हालांकि, ऐसे मामलों में जहां टेम्पलेट तर्क कटौती को सुविधाजनक बनाने के लिए इस फ़ंक्शन का एक साथ उल्लेख नहीं किया गया है, संकलक टेम्पलेट तर्कों को कम करने में विफल रहेगा। तो प्रिंट लाइन 2 और 3. अब हटाने आप ध्यान देंगे कि यह लाइन 1 प्रिंट, रुक जाता है,:

+1

शानदार जवाब। फ़्लश ने कहीं और कैसे काम किया है इस बारे में गुणवत्ता की जानकारी नहीं मिली। – Michael

22

डिफ़ॉल्ट रूप से, std::cout buffered है, और वास्तविक आउटपुट केवल बफर भरने के बाद मुद्रित होता है या कुछ अन्य फ्लशिंग स्थिति होती है (उदाहरण के लिए स्ट्रीम में एक नई पंक्ति)। कभी-कभी आप यह सुनिश्चित करना चाहते हैं कि प्रिंटिंग तुरंत हो, और आपको मैन्युअल रूप से फ़्लश करने की आवश्यकता है।

उदाहरण के लिए, मान लीजिए आप एक एकल डॉट मुद्रण द्वारा एक प्रगति रिपोर्ट रिपोर्ट करना चाहते हैं:

फ्लशिंग के बिना, आप एक बहुत लंबे समय के लिए उत्पादन नहीं दिखाई देगा।

ध्यान दें कि std::endl स्ट्रीम में एक नई लाइन के साथ-साथ इसे फ्लश करने का कारण बनता है। चूंकि फ्लशिंग बहुत महंगा है, std::endl को फ्लशिंग स्पष्ट रूप से वांछित नहीं होने पर अत्यधिक उपयोग नहीं किया जाना चाहिए।

+4

पाठकों के लिए बस एक अतिरिक्त नोट: 'cout' एकमात्र चीज नहीं है यह सी ++ में buffered है। सामान्यतः 'ओस्ट्रीम' डिफ़ॉल्ट रूप से डिफ़ॉल्ट रूप से बफर किया जाता है, जिसमें 'fstream's और like भी शामिल है। – Cornstalks

+0

'cin' का उपयोग करके आउटपुट को फ़्लश करने से पहले करता है, नहीं? – Bateman

4

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

जब आप स्ट्रीम को फ्लश करते हैं, तो यह भाषा पुस्तकालयों, ओएस और हार्डवेयर को बताता है कि आप किसी भी पात्र को चाहते हैं जिसे आपके पास अब तक आउटपुट है ताकि भंडारण के लिए सभी तरह से मजबूर किया जा सके। सैद्धांतिक रूप से, 'फ्लश' के बाद, आप दीवार से बाहर कॉर्ड लात मार सकते हैं और उन पात्रों को अभी भी सुरक्षित रूप से संग्रहीत किया जाएगा।

मुझे यह उल्लेख करना चाहिए कि ओएस ड्राइवर लिखने वाले लोग या डिस्क ड्राइव को डिजाइन करने वाले लोग एक सुझाव के रूप में 'फ्लश' का उपयोग करने के लिए स्वतंत्र हो सकते हैं और वे वास्तव में वर्णों को लिख नहीं सकते हैं। आउटपुट बंद होने पर भी, वे उन्हें बचाने के लिए थोड़ी देर इंतजार कर सकते हैं। (याद रखें कि ओएस एक ही समय में सभी प्रकार की चीजें करता है और यह आपके बाइट्स को संभालने के लिए दूसरे या दो का इंतजार करने में अधिक सक्षम हो सकता है।)

तो फ्लश एक प्रकार का चेकपॉइंट है।

एक और उदाहरण: यदि आउटपुट कंसोल डिस्प्ले पर जा रहा है, तो फ्लश यह सुनिश्चित करेगा कि पात्र वास्तव में उन सभी जगहों पर पहुंच जाएंगे जहां उपयोगकर्ता उन्हें देख सकता है। जब आप कुंजीपटल इनपुट की अपेक्षा कर रहे हों तो यह एक महत्वपूर्ण बात है। अगर आपको लगता है कि आपने कंसोल पर एक प्रश्न लिखा है और यह अभी भी कुछ आंतरिक बफर में फंस गया है, तो उपयोगकर्ता को यह नहीं पता कि उत्तर में क्या टाइप करना है। तो, यह एक ऐसा मामला है जहां फ्लश महत्वपूर्ण है।

8

यहाँ एक छोटी कार्यक्रम है कि आप का पालन करने के क्या फ्लश कर रही है

#include <iostream> 
#include <unistd.h> 

using namespace std; 

int main() { 

    cout << "Line 1..." << flush; 

    usleep(500000); 

    cout << "\nLine 2" << endl; 

    cout << "Line 3" << endl ; 

    return 0; 
} 

भागो इस कार्यक्रम लिख सकते है फ्लश कॉल करें और प्रोग्राम को फिर से चलाएं- आप देखेंगे कि प्रोग्राम रुक गया है और फिर एक ही समय में सभी 3 लाइनों को प्रिंट करता है। पहली पंक्ति प्रोग्राम रोक से पहले बफर की जाती है, लेकिन क्योंकि बफर कभी नहीं फिसल जाता है, लाइन 1 को लाइन 2 से एंडल कॉल तक आउटपुट नहीं किया जाता है।

संबंधित मुद्दे