वहाँ उत्कृष्ट उत्तर हैं, इसलिए मैं अभी कुछ चीजें भूल गया हूं।
0. RAII स्कोप के बारे में है
RAII दोनों के बारे में है:
- कंस्ट्रक्टर में रिसोर्स (चाहे कोई भी रिसोर्स) हो, और उसे डिस्ट्रक्टर में अन-एक्वायर करना।
- कंस्ट्रक्टर को निष्पादित किया जाता है जब चर घोषित किया जाता है, और विध्वंसक स्वचालित रूप से निष्पादित होता है जब चर दायरे से बाहर हो जाता है।
दूसरों ने पहले ही इस बारे में जवाब दिया, इसलिए मैं विस्तृत नहीं करूंगा।
1. जब जावा या C # में कोडिंग करते हैं, तो आप पहले से ही RAII का उपयोग करते हैं ...
महाशूरुद्दीन: क्या! जब मैं कहता हूं, "निकोल, मुझे मेरी चप्पल लाकर दे, और मुझे मेरी रात दे," यह गद्य है?
फिलिप मास्टर: जी, सर।
महाशूरोदय: चालीस से अधिक वर्षों से मैं इसके बारे में कुछ भी जाने बिना गद्य बोल रहा हूं, और मुझे सिखाने के लिए मैं आपका बहुत आभारी हूं।
- मोलियार: द मिडिल क्लास जेंटलमैन, एक्ट 2, दृश्य 4
जैसा कि महाशय जर्सडेन ने गद्य के साथ किया था, C # और यहां तक कि जावा के लोग पहले से ही RAII का उपयोग करते हैं, लेकिन छिपे हुए तरीकों से। उदाहरण के लिए, निम्नलिखित जावा कोड (जिसे C # के synchronized
साथ बदलकर उसी तरह लिखा गया है lock
):
void foo()
{
// etc.
synchronized(someObject)
{
// if something throws here, the lock on someObject will
// be unlocked
}
// etc.
}
... पहले से ही RAII का उपयोग कर रहा है: म्यूटेक्स अधिग्रहण कीवर्ड ( synchronized
या lock
) में किया जाता है , और गुंजाइश से बाहर निकलने पर संयुक्त अधिग्रहण किया जाएगा।
यह अपने अंकन में इतना स्वाभाविक है कि इसे लगभग उन लोगों के लिए भी स्पष्टीकरण की आवश्यकता है जो RAII के बारे में कभी नहीं सुनते हैं।
C ++ में जावा और C # से अधिक लाभ यह है कि RAII का उपयोग करके कुछ भी बनाया जा सकता है। उदाहरण के लिए, C ++ में synchronized
न तो कोई सीधा बिल्ड-इन समतुल्य है lock
, लेकिन हम फिर भी उन्हें रख सकते हैं।
C ++ में, यह लिखा जाएगा:
void foo()
{
// etc.
{
Lock lock(someObject) ; // lock is an object of type Lock whose
// constructor acquires a mutex on
// someObject and whose destructor will
// un-acquire it
// if something throws here, the lock on someObject will
// be unlocked
}
// etc.
}
जिसे आसानी से Java / C # तरीके से लिखा जा सकता है (C ++ macros का उपयोग करके):
void foo()
{
// etc.
LOCK(someObject)
{
// if something throws here, the lock on someObject will
// be unlocked
}
// etc.
}
2. RAII के वैकल्पिक उपयोग हैं
WHITE RABBIT: [गायन] मैं देर से / बहुत देर से / बहुत महत्वपूर्ण तारीख के लिए हूँ। / "हैलो" कहने का समय नहीं है। / अलविदा। / मैं लेट हो गया, मैं लेट हो गया, लेट हो गया।
- एलिस इन वंडरलैंड (डिज्नी संस्करण, 1951)
आपको पता है कि कंस्ट्रक्टर को कब (ऑब्जेक्ट डिक्लेरेशन पर) कहा जाएगा, और आप जानते हैं कि इसके संबंधित डिस्ट्रक्टर को कब (स्कोप के बाहर निकलने पर) कहा जाएगा, इसलिए आप एक लाइन के साथ लगभग जादुई कोड लिख सकते हैं। C ++ वंडरलैंड में आपका स्वागत है (कम से कम, C ++ डेवलपर के दृष्टिकोण से)।
उदाहरण के लिए, आप एक काउंटर ऑब्जेक्ट लिख सकते हैं (मैं इसे एक अभ्यास के रूप में देता हूं) और इसके चर को घोषित करके इसका उपयोग करता हूं, जैसे कि ऊपर की लॉक ऑब्जेक्ट का उपयोग किया गया था:
void foo()
{
double timeElapsed = 0 ;
{
Counter counter(timeElapsed) ;
// do something lengthy
}
// now, the timeElapsed variable contain the time elapsed
// from the Counter's declaration till the scope exit
}
जो निश्चित रूप से लिखा जा सकता है, फिर से, जावा / सी # मैक्रो का उपयोग करके रास्ता:
void foo()
{
double timeElapsed = 0 ;
COUNTER(timeElapsed)
{
// do something lengthy
}
// now, the timeElapsed variable contain the time elapsed
// from the Counter's declaration till the scope exit
}
3. C ++ की कमी क्यों है finally
?
[के बारे में] यह अंतिम उलटी गिनती है!
- यूरोप: अंतिम उलटी गिनती (क्षमा करें, मैं उद्धरण से बाहर था, यहाँ ... :-)
finally
(या तो एक के माध्यम से खंड दायरे से बाहर निकलने के मामले में संसाधन निपटान को संभालने के लिए सी # / जावा में प्रयोग किया जाता है return
या एक फेंक दिया अपवाद)।
Astute विनिर्देशन पाठकों ने ध्यान दिया होगा C ++ में अंत में कोई खंड नहीं है। और यह कोई त्रुटि नहीं है, क्योंकि C ++ को इसकी आवश्यकता नहीं है, क्योंकि RAII पहले से ही संसाधन निपटान को संभालता है। (और मेरा विश्वास करो, सी ++ विध्वंसक लिखना सही जावा अंत में क्लॉज, या यहां तक कि एक सी # सही डिस्पोज विधि लिखने से अधिक परिमाण है)।
फिर भी, कभी-कभी, एक finally
खंड शांत होगा। क्या हम इसे C ++ में कर सकते हैं? हाँ हम कर सकते हैं! और फिर से RAII के वैकल्पिक उपयोग के साथ।
निष्कर्ष: RAII C ++ में दर्शन से अधिक है: यह C ++ है
आरए II? यह सी ++ है !!!
- सी ++ डेवलपर की अपमानजनक टिप्पणी, एक अस्पष्ट स्पार्टा राजा और उसके 300 दोस्तों द्वारा बेशर्मी से नकल की गई
जब आप C ++ में अनुभव के कुछ स्तर पर पहुंच जाते हैं, तो आप RAII के संदर्भ में, बाधाओं और विनाशकारी स्वचालित निष्पादन के संदर्भ में सोचना शुरू कर देते हैं ।
आप के मामले में सोचना शुरू स्कोप , और {
और }
पात्रों अपने कोड में सबसे महत्वपूर्ण में से लोगों को हो गया है।
और लगभग सब कुछ RAII के संदर्भ में सही बैठता है: अपवाद सुरक्षा, म्यूटेक्स, डेटाबेस कनेक्शन, डेटाबेस अनुरोध, सर्वर कनेक्शन, घड़ियां, ओएस हैंडल, आदि, और अंतिम, लेकिन कम से कम, मेमोरी नहीं।
डेटाबेस का हिस्सा नगण्य नहीं है, जैसे कि, यदि आप मूल्य का भुगतान करना स्वीकार करते हैं, तो आप " ट्रांसेक्शनल प्रोग्रामिंग " शैली में भी लिख सकते हैं, निर्णय लेने तक कोड की पंक्तियों और लाइनों को निष्पादित करना, अंत में, यदि आप सभी परिवर्तन करना चाहते हैं। , या, यदि संभव न हो, तो सभी परिवर्तन वापस लौट आए (जब तक कि प्रत्येक पंक्ति कम से कम मजबूत अपवाद गारंटी को पूरा करती है)। ( लेन-देन प्रोग्रामिंग के लिए इस हर्ब के सटर लेख का दूसरा भाग देखें )।
और एक पहेली की तरह, सब कुछ फिट बैठता है।
RAII C ++ का इतना हिस्सा है, C ++ इसके बिना C ++ नहीं हो सकता है।
यह बताता है कि अनुभवी C ++ डेवलपर्स RAII के साथ क्यों आसक्त हैं, और RAII पहली चीज क्यों है जो वे किसी अन्य भाषा की कोशिश करते समय खोजते हैं।
और यह बताता है कि क्यों गार्बेज कलेक्टर, जबकि प्रौद्योगिकी का एक शानदार टुकड़ा, अपने आप में C ++ के विकास के दृष्टिकोण से इतना प्रभावशाली नहीं है:
- आरएआई पहले से ही एक जीसी द्वारा संभाले गए अधिकांश मामलों को संभालता है
- शुद्ध प्रबंधित वस्तुओं पर गोलाकार संदर्भों के साथ एक GC रास से बेहतर व्यवहार करता है (कमजोर बिंदुओं के स्मार्ट उपयोग से कम)
- फिर भी A GC स्मृति तक सीमित है, जबकि RAII किसी भी प्रकार के संसाधन को संभाल सकता है।
- जैसा कि ऊपर वर्णित है, RAII बहुत कुछ कर सकता है ...