RAII क्या है? उदाहरण?


19

हमेशा जब RAII शब्द का उपयोग किया जाता है, तो लोग वास्तव में आरंभिकता के बजाय डिकंस्ट्रक्शन के बारे में बात कर रहे हैं। मुझे लगता है कि मेरे पास एक बुनियादी समझ है कि इसका क्या मतलब हो सकता है लेकिन मुझे यकीन नहीं है। भी: C ++ केवल RAII भाषा है? Java या C # / NET के बारे में क्या?

जवाबों:


25

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

मान लें कि आप कुछ कोड लिखना चाहते हैं, जहां आप विंडो कर्सर को प्रतीक्षा में बदलने जा रहे हैं (घंटा, डोनट-ऑफ-नॉट-वर्किंग, आदि) कर्सर, अपना सामान करें, और फिर इसे वापस बदल दें। और यह भी कहें कि "अपना सामान करो" एक अपवाद फेंक सकता है। ऐसा करने का RAII तरीका एक ऐसा वर्ग बनाना होगा जिसके ctor ने प्रतीक्षा करने के लिए कर्सर सेट किया था, जिसकी एक "वास्तविक" विधि ने जो भी आप करना चाहते थे, किया और जिसके dtor ने कर्सर को वापस सेट किया। संसाधन (इस स्थिति में कर्सर राज्य) किसी वस्तु के दायरे से बंधा होता है। जब आप संसाधन प्राप्त करते हैं तो आप किसी ऑब्जेक्ट को इनिशियलाइज़ करते हैं। यदि अपवाद को फेंक दिया जाता है, तो आप नष्ट होने वाली वस्तु पर भरोसा कर सकते हैं और इसका मतलब है कि आप संसाधन को साफ करने के लिए भरोसा कर सकते हैं।

RAII का उपयोग करने का मतलब है कि आपको इसकी आवश्यकता नहीं है finally। बेशक, यह नियतात्मक विनाश पर निर्भर करता है, जो आपके पास जावा में नहीं हो सकता है। आप C # और VB.NET में नियतात्मक विनाश का एक प्रकार प्राप्त कर सकते हैं using


4
मुझे लगता है कि यह वही है जो आप प्राप्त कर रहे हैं, लेकिन आप यह जोड़ना चाह सकते हैं कि जिस कारण से जावा और C # RAII का समर्थन नहीं करते हैं, वह कचरा संग्रहकर्ता के कारण है। C ++ में, स्कोप से बाहर जाते ही एक स्थानीय वस्तु नष्ट हो जाएगी। Java / C # में यह सच नहीं है।
जेसन बेकर

जेसन बिंदु पर विस्तार करते हुए, जावा और सी # समय पर विनाश की गारंटी नहीं दे सकता है इसका कारण संदर्भ चक्र की संभावना है, जिसका अर्थ है कि विनाशकों को चलाने के लिए एक सुरक्षित आदेश निर्धारित करना असंभव है। संदर्भ चक्र C ++ में भी हो सकता है, लेकिन निहितार्थ अलग-अलग होते हैं - प्रोग्रामर विनाश के आदेश को निर्धारित करने और कुछ डिलीट करने के लिए जिम्मेदार हो जाता है। उस जिम्मेदारी को अक्सर कुछ उच्च-स्तरीय कक्षाओं के विध्वंसक में पैक किया जाता है - उदाहरण के लिए एक कंटेनर वर्ग सभी निहित वस्तुओं को नष्ट करने के लिए सुनिश्चित करने के लिए जिम्मेदार है। "स्वामित्व" कुंजी है।
स्टीव 314

1
@ जेसन कि मुझे "नियतात्मक विनाश" से क्या मतलब है - एक सी ++ प्रोग्रामर जानता है कि विध्वंसक कब चलेगा।
केट ग्रेगरी

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

1
@PerJohansson हाँ, आप ctor में अधिग्रहण करते हैं। और आप डोर में जारी करते हैं। मैं दूसरे बिंदु पर ध्यान केंद्रित कर रहा था, लेकिन वे एक साथ चलते हैं। एक बार ctor हो जाने के बाद आपको पता चलता है कि आपके पास एक वैध ऑब्जेक्ट है। और आप जानते हैं कि चाहे कुछ भी हो, संसाधन सही समय पर जारी किया जाएगा।
केट ग्रेगोरी

4

RAII आंशिक रूप से यह तय करने के बारे में है कि जब कोई वस्तु अपने स्वयं के क्लीनअप के लिए जिम्मेदार हो जाती है - नियम यह है कि वस्तु तब जिम्मेदार हो जाती है जब उसका निर्माणकर्ता प्रारंभिककरण पूरा करता है। इनिशियलाइजेशन और क्लीनअप, कंस्ट्रक्टर और डिस्ट्रक्टर की समरूपता का मतलब है कि दोनों का एक-दूसरे से घनिष्ठ संबंध है।

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

लेकिन क्या होता है अगर अपवाद फेंक एक निर्माता के भीतर होता है?

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

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

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

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