जवाबों:
यह आसान है जब आपके पास ऐसे गुण हैं जो आप प्रत्येक स्मार्ट पॉइंटर को असाइन कर सकते हैं। तीन महत्वपूर्ण गुण हैं।
पहला अर्थ यह है कि स्मार्ट पॉइंटर ऑब्जेक्ट को हटा नहीं सकता है, क्योंकि यह इसका मालिक नहीं है। दूसरे का मतलब है कि केवल एक ही स्मार्ट पॉइंटर कभी भी एक ही समय में एक ही ऑब्जेक्ट को इंगित कर सकता है। यदि स्मार्ट पॉइंटर को फ़ंक्शंस से लौटाया जाना है, तो स्वामित्व को लौटे स्मार्ट पॉइंटर में स्थानांतरित किया जाता है, उदाहरण के लिए।
तीसरे का मतलब है कि एक ही समय में कई स्मार्ट पॉइंटर्स एक ही ऑब्जेक्ट को इंगित कर सकते हैं। यह कच्चे पॉइंटर पर भी लागू होता है, हालांकि कच्चे पॉइंटर्स में एक महत्वपूर्ण विशेषता की कमी होती है: वे परिभाषित नहीं करते हैं कि वे मालिक हैं या नहीं। स्वामित्व स्मार्ट पॉइंटर का एक हिस्सा ऑब्जेक्ट को हटा देगा यदि हर मालिक ऑब्जेक्ट को छोड़ देता है। यह व्यवहार अक्सर आवश्यक होता है, इसलिए साझा किए गए स्मार्ट पॉइंटर्स व्यापक रूप से फैलते हैं।
कुछ मालिक स्मार्ट पॉइंटर्स न तो दूसरे और न ही तीसरे का समर्थन करते हैं। इसलिए उन्हें फ़ंक्शंस से नहीं लौटाया जा सकता है या कहीं और पारित नहीं किया जा सकता है। यह उन RAII
उद्देश्यों के लिए सबसे उपयुक्त है जहां स्मार्ट पॉइंटर को स्थानीय रखा जाता है और इसे सिर्फ इसलिए बनाया जाता है ताकि यह किसी वस्तु को दायरे से बाहर जाने के बाद मुक्त कर दे।
कॉपी कंस्ट्रक्टर होने से स्वामित्व का हिस्सा लागू किया जा सकता है। यह स्वाभाविक रूप से एक स्मार्ट पॉइंटर को कॉपी करता है और कॉपी और ओरिजिनल दोनों एक ही ऑब्जेक्ट को संदर्भित करेगा। स्वामित्व का स्थानांतरण वास्तव में C ++ में लागू नहीं किया जा सकता है, क्योंकि भाषा द्वारा समर्थित एक वस्तु से दूसरी वस्तु को स्थानांतरित करने का कोई साधन नहीं है: यदि आप किसी फ़ंक्शन से किसी ऑब्जेक्ट को वापस करने का प्रयास करते हैं, तो क्या हो रहा है कि ऑब्जेक्ट की प्रतिलिपि बनाई गई है। तो एक स्मार्ट पॉइंटर जो स्वामित्व के हस्तांतरण को लागू करता है, उसे स्वामित्व के हस्तांतरण को लागू करने के लिए प्रतिलिपि निर्माता का उपयोग करना पड़ता है। हालांकि, यह बदले में कंटेनरों में इसके उपयोग को तोड़ता है, क्योंकि आवश्यकताएं कंटेनर के तत्वों के प्रतिलिपि निर्माता के एक निश्चित व्यवहार को बताती हैं जो इन स्मार्ट पॉइंटर्स के तथाकथित "मूविंग कंस्ट्रक्टर" व्यवहार के साथ असंगत है।
C ++ 1x तथाकथित "मूव कंस्ट्रक्टर्स" और "मूव असाइनमेंट ऑपरेटर्स" को शुरू करके ट्रांसफर-ऑफ-स्वामित्व के लिए मूल समर्थन प्रदान करता है। यह ऐसे ट्रांसफर-ऑफ-ओनरशिप स्मार्ट पॉइंटर भी कहा जाता है unique_ptr
।
scoped_ptr
एक स्मार्ट पॉइंटर है जो न तो हस्तांतरणीय है और न ही पहनने योग्य है। यह केवल उपयोग करने योग्य है यदि आपको स्थानीय रूप से मेमोरी आवंटित करने की आवश्यकता है, लेकिन यह सुनिश्चित करें कि यह फिर से मुक्त हो जाए जब यह दायरे से बाहर हो जाए। लेकिन अगर आप ऐसा करने की इच्छा रखते हैं, तो इसे दूसरे scoped_ptr के साथ स्वैप किया जा सकता है।
shared_ptr
एक स्मार्ट पॉइंटर है जो स्वामित्व को साझा करता है (ऊपर तीसरा प्रकार)। यह संदर्भित संदर्भ है इसलिए यह देख सकता है कि इसकी अंतिम प्रति कब दायरे से बाहर हो जाती है और फिर यह प्रबंधित वस्तु को मुक्त कर देती है।
weak_ptr
एक गैर-स्वामित्व वाला स्मार्ट पॉइंटर है। इसका उपयोग एक संदर्भ संख्या को जोड़ने के बिना एक प्रबंधित वस्तु (एक साझा_प्रक्रम द्वारा प्रबंधित) को संदर्भित करने के लिए किया जाता है। आम तौर पर, आपको कच्चे पॉइंटर को share_ptr से बाहर निकालना होगा और इसे चारों ओर कॉपी करना होगा। लेकिन यह सुरक्षित नहीं होगा, क्योंकि आपके पास यह जांचने का कोई तरीका नहीं होगा कि वस्तु वास्तव में कब हटाई गई। तो, weak_ptr द्वारा साझा किए गए ऑब्जेक्ट को संदर्भित करके साधन प्रदान करता है। यदि आपको ऑब्जेक्ट को एक्सेस करने की आवश्यकता है, तो आप इसके प्रबंधन को लॉक कर सकते हैं (इससे बचने के लिए किसी अन्य थ्रेड में एक साझा_पार्टर ऑब्जेक्ट का उपयोग करते समय इसे मुक्त करता है) और फिर इसका उपयोग करें। यदि पहले से हटाए गए ऑब्जेक्ट के लिए weak_ptr इंगित करता है, तो यह आपको एक अपवाद फेंककर नोटिस करेगा। कमजोर चक्रीय का उपयोग करना सबसे अधिक फायदेमंद है जब आपके पास चक्रीय संदर्भ होता है: संदर्भ गिनती आसानी से ऐसी स्थिति का सामना नहीं कर सकती है।
intrusive_ptr
एक शेयर्ड_एप्ट्र की तरह है, लेकिन यह रेफरेंस काउंट को एक शेयर्ड_प्ट्र में नहीं रखता है, लेकिन कुछ हेल्पर फंक्शन्स के लिए काउंट को बढ़ाता / घटाता है, जिसे मैनेज किए गए ऑब्जेक्ट द्वारा परिभाषित करने की आवश्यकता होती है। इसका यह लाभ है कि पहले से संदर्भित ऑब्जेक्ट (जिसमें एक बाहरी संदर्भ गिनती तंत्र द्वारा बढ़ाई गई संदर्भ संख्या है) को एक घुसपैठ_प्रात में भरा जा सकता है - क्योंकि संदर्भ संख्या अब स्मार्ट पॉइंटर के लिए आंतरिक नहीं है, लेकिन स्मार्ट पॉटर एक मौजूदा का उपयोग करता है संदर्भ गिनती तंत्र।
unique_ptr
स्वामित्व सूचक का स्थानांतरण है। आप इसे कॉपी नहीं कर सकते, लेकिन आप इसे C ++ 1x के मूव कंस्ट्रक्टर्स का उपयोग करके स्थानांतरित कर सकते हैं:
unique_ptr<type> p(new type);
unique_ptr<type> q(p); // not legal!
unique_ptr<type> r(move(p)); // legal. p is now empty, but r owns the object
unique_ptr<type> s(function_returning_a_unique_ptr()); // legal!
यह वह शब्दार्थ है जो std :: auto_ptr का पालन करता है, लेकिन हिलाने के लिए मूल समर्थन गायब होने के कारण, यह उन्हें नुकसान के बिना प्रदान करने में विफल रहता है। unique_ptr स्वचालित रूप से अस्थायी अस्थायी अनूठे_ptr से संसाधनों की चोरी करेगा जो चाल शब्दार्थों की प्रमुख विशेषताओं में से एक है। auto_ptr को अगले C ++ मानक रिलीज में unique_ptr के पक्ष में हटा दिया जाएगा। C ++ 1x उन वस्तुओं को भी भरने की अनुमति देगा जो केवल चल योग्य हैं, लेकिन कंटेनरों में प्रतिलिपि योग्य नहीं हैं। उदाहरण के लिए, आप यूनिक_प्रेट को वेक्टर में स्टफ कर सकते हैं। यदि आप इस बारे में अधिक पढ़ना चाहते हैं तो मैं यहां रुकूंगा और इसके बारे में एक अच्छा लेख लिखूंगा।
auto_ptr
पहले से ही पदावनत है (C ++ 11)।
intrusive_ptr
हो सकता है shared_ptr
। स्पष्ट रूप से कैश बेहतर प्रदर्शन करता है यदि आप संदर्भ संख्या को एक अलग ऑब्जेक्ट के बजाय प्रबंधित ऑब्जेक्ट की मेमोरी के हिस्से के रूप में संग्रहीत करते हैं। यह प्रबंधित ऑब्जेक्ट के टेम्पलेट या सुपरक्लास में लागू किया जा सकता है।
scoped_ptr सबसे सरल है। जब यह दायरे से बाहर हो जाता है, तो यह नष्ट हो जाता है। निम्नलिखित कोड अवैध है (scoped_ptrs गैर-प्रतिलिपि योग्य हैं) लेकिन एक बिंदु को स्पष्ट करेगा:
std::vector< scoped_ptr<T> > tPtrVec;
{
scoped_ptr<T> tPtr(new T());
tPtrVec.push_back(tPtr);
// raw T* is freed
}
tPtrVec[0]->DoSomething(); // accessing freed memory
shared_ptr को संदर्भ गिना जाता है। जब भी कोई प्रति या असाइनमेंट होता है, संदर्भ गणना बढ़ जाती है। हर बार एक उदाहरण के विध्वंसक को निकाल दिया जाता है, कच्चे टी * के लिए संदर्भ संख्या में कमी की जाती है। एक बार जब यह 0 होता है, तो पॉइंटर को मुक्त कर दिया जाता है।
std::vector< shared_ptr<T> > tPtrVec;
{
shared_ptr<T> tPtr(new T());
// This copy to tPtrVec.push_back and ultimately to the vector storage
// causes the reference count to go from 1->2
tPtrVec.push_back(tPtr);
// num references to T goes from 2->1 on the destruction of tPtr
}
tPtrVec[0]->DoSomething(); // raw T* still exists, so this is safe
weak_ptr एक साझा पॉइंटर का एक कमजोर-संदर्भ है जिसकी आपको यह देखने के लिए जांच करने की आवश्यकता है कि क्या पॉइंट-टू- शेयर्ड_ptr अभी भी आसपास है
std::vector< weak_ptr<T> > tPtrVec;
{
shared_ptr<T> tPtr(new T());
tPtrVec.push_back(tPtr);
// num references to T goes from 1->0
}
shared_ptr<T> tPtrAccessed = tPtrVec[0].lock();
if (tPtrAccessed[0].get() == 0)
{
cout << "Raw T* was freed, can't access it"
}
else
{
tPtrVec[0]->DoSomething(); // raw
}
intrusive_ptr का उपयोग आम तौर पर तब किया जाता है जब कोई 3rd पार्टी स्मार्ट ptr होता है जिसका आपको उपयोग करना चाहिए। यह संदर्भ संख्या को जोड़ने और घटाने के लिए एक निशुल्क फ़ंक्शन को कॉल करेगा । अधिक जानकारी के लिए दस्तावेज़ को बढ़ावा देने के लिए लिंक देखें ।
if (tPtrAccessed[0].get() == 0)
माना जाता है if (tPtrAccessed.get() == 0)
?
boost::ptr_container
स्मार्ट पॉइंटर्स को बढ़ावा देने के किसी भी सर्वेक्षण में अनदेखी न करें । वे उन स्थितियों में अमूल्य हो सकते हैं, जैसे एक std::vector<boost::shared_ptr<T> >
बहुत धीमा होगा।
मैं प्रलेखन को देखने के बारे में सलाह देता हूं। यह उतना डरावना नहीं है जितना लगता है। और कुछ छोटे संकेत:
scoped_ptr
- यह कार्यक्षेत्र से बाहर जाने पर एक सूचक स्वचालित रूप से हटा दिया जाता है। नोट - कोई असाइनमेंट संभव नहीं है, लेकिन ओवरहेड का परिचय नहीं देता हैintrusive_ptr
- रेफरेंस काउंटिंग पॉइंटर जिसका ओवरहेड नहीं है smart_ptr
। हालाँकि ऑब्जेक्ट स्वयं संदर्भ संख्या संग्रहीत करता हैweak_ptr
- shared_ptr
परिपत्र निर्भरता के परिणामस्वरूप स्थितियों से निपटने के लिए एक साथ काम करता है (प्रलेखन पढ़ें, और अच्छी तस्वीर के लिए Google पर खोज करें;)shared_ptr
- स्मार्ट पॉइंटर्स के जेनेरिक, सबसे शक्तिशाली (और हैवीवेट)auto_ptr
, जो यह सुनिश्चित करता है कि जिस बिंदु पर नियंत्रण होता है वह वस्तु अपने आप नष्ट हो जाती है। हालाँकि इसमें बाकी लोगों की तुलना में अलग-अलग कॉपी शब्दार्थ हैं।unique_ptr
- C ++ 0x के साथ आएगाप्रतिक्रिया संपादित करने के लिए: हाँ