2011-01-02 27 views
18

मैं स्मार्ट पॉइंटर्स (std::auto_ptr) के बारे में सीख रहा हूं और बस here और here पढ़ता हूं कि स्मार्ट पॉइंटर्स (std::auto_ptr) को कंटेनरों में नहीं रखा जाना चाहिए (यानी std::vector) क्योंकि अधिकांश कंपाइलर शिकायत नहीं करेंगे और यह सही प्रतीत हो सकता है। ऐसा कोई नियम नहीं है जो कहता है कि स्मार्ट पॉइंटर्स को आंतरिक रूप से कॉपी नहीं किया जाएगा (उदाहरण के लिए vector वर्ग द्वारा) और अपने स्वामित्व को स्थानांतरित करें, तो सूचक पूर्ण हो जाएगा। अंत में, सबकुछ खराब हो जाएगा।Std :: वेक्टर जैसे कंटेनर में स्मार्ट पॉइंटर्स?

हकीकत में, यह कितनी बार होता है?

कभी-कभी मेरे पास पॉइंटर्स के वैक्टर होते हैं और यदि भविष्य में मैं निर्णय लेता हूं कि मैं स्मार्ट पॉइंटर्स का वेक्टर रखना चाहता हूं तो मेरे विकल्प क्या होंगे?

मुझे सी ++ 0x और बूस्ट पुस्तकालयों के बारे में पता है, लेकिन अभी के लिए, मैं एक एसटीएल दृष्टिकोण से चिपकना पसंद करूंगा।

+2

std :: tr1 (std :: tr1 :: shared_ptr) में स्मार्ट पॉइंटर्स भी हैं –

+1

मैं वास्तव में एक स्मार्ट पॉइंटर 'auto_ptr' नहीं कहूंगा :) यह वास्तव में बहुत मूर्खतापूर्ण है, और इसलिए स्मार्ट पॉइंटर्स के बारे में अधिकतर सलाह नहीं दे सकती हैं (दुर्भाग्य से) इसके लिए लागू किया जाना चाहिए (इसकी खराब प्रतिलिपि semantics के कारण)। –

उत्तर

16

हां, आप वास्तव में मानक कंटेनरों के साथ std::auto_ptr का उपयोग नहीं कर सकते हैं। std::auto_ptr प्रतियां बराबर नहीं हैं, और क्योंकि मानक कंटेनर (और एल्गोरिदम) को उनके तत्वों की प्रतिलिपि बनाने की अनुमति है, यह चीजों को खराब कर देगा। यही है, std::auto_ptr की प्रतिलिपि बनाने का ऑपरेशन किसी ऑब्जेक्ट की प्रतिलिपि की तुलना में अन्य का अर्थ है: इसका अर्थ है स्वामित्व स्थानांतरित करना

आपके विकल्प हैं:

  1. Boost Smart Pointers library का प्रयोग करें। यह तर्कसंगत रूप से आपका सबसे अच्छा विकल्प है।
  2. आदिम पॉइंटर्स का उपयोग करें। यह तेज़ और सुरक्षित है, जब तक आप पॉइंटर्स को सही तरीके से प्रबंधित करते हैं। कभी-कभी यह जटिल या मुश्किल हो सकता है। उदाहरण के लिए, आपको अपने आप को डबल-डिलीट मुद्दों से निपटने (टालना) का सामना करना पड़ेगा।
  3. अपने स्वयं के संदर्भ-गणना स्मार्ट सूचक का उपयोग करें। वह मूर्खतापूर्ण होगा; बूस्ट स्मार्ट पॉइंटर का उपयोग करें।
+3

बूस्ट की 'ptr_vector' और समान रूप से मत भूलना। – etarion

+8

यदि आप ओ ना कंपाइलर हैं जो इसका समर्थन करते हैं, तो 'unique_ptr' भी एक विकल्प है। – jalf

+2

मैं इस विचार से असहमत हूं कि 'shared_ptr' सबसे अच्छा विकल्प है। मैं उन्हें अंतिम उपाय विकल्प के रूप में देखता हूं, क्योंकि साझा स्वामित्व आजीवन अनिश्चितता के कारण कई मुद्दों को लाता है: हाँ जब तक आपको इसकी आवश्यकता हो, तब तक वस्तु जीवित रहेगी, लेकिन इससे भी ज़्यादा ज़िंदा रह सकती है, खासकर यदि आप अनजाने में संदर्भों का एक चक्र बनाएं ... –

9

समस्या आप चिंताओं के auto_ptr यह प्रति पर स्वामित्व ले जाता है के बाद से बात कर रहे हैं। shared_ptr और unique_ptr कंटेनरों के साथ बस ठीक काम करते हैं।

3

किसी भी प्रकार की है कि आप एक मानक कंटेनर टेम्पलेट के साथ उपयोग करने वाले कंटेनर के लिए आवश्यकताओं के साथ पालन करना चाहिए। विशेष रूप से, प्रकार CopyConstructible और आबंटित प्रकार के लिए आवश्यकताओं को पूरा करना होगा।

कई स्मार्ट संकेत दिए गए इन आवश्यकताओं को पूरा करते हैं और मानक कंटेनर के साथ इस्तेमाल किया जा सकता है, लेकिन std::auto_ptr उनमें से एक नहीं है, क्योंकि std::auto_ptr की प्रतियां स्रोत है कि वे बनाए गए थे या से सौंपा के बराबर नहीं हैं।

हालांकि मानक कंटेनर के कुछ कार्यान्वयन कुछ स्थितियों में auto_ptr साथ काम कर सकते यह इस तरह कार्यान्वयन विवरण पर भरोसा करने के लिए खतरनाक है।

2

सैद्धांतिक रूप से आप एसटीएल कंटेनर के साथ std::auto_ptr उपयोग कर सकते हैं, तो आप पूरी तरह से अपने आंतरिक कार्यान्वयन को समझते हैं और कुछ भी है कि auto_ptr स्वामित्व खो सकते हैं ऐसा नहीं करते हैं, लेकिन व्यावहारिक रूप से यह कच्चे ptrs साथ कंटेनर का उपयोग करने के लिए और अधिक सुरक्षित है।

"वास्तव में, यह कितनी बार होता है?" - अपने आप से बहुत खतरनाक सवाल है।सबसे पहले, एसटीएल - यह एक मानक मानक कार्यान्वयन नहीं है, कई हैं। प्रत्येक व्यक्ति अलग-अलग तरीकों से कंटेनरों को कार्यान्वित कर सकता है, इसलिए आपके अत्यधिक ट्यून किए गए कोड "कंटेनरों में auto_ptr" खानों से बचने के लिए किसी अन्य एसटीएल कार्यान्वयन पर स्विच कर सकते हैं। साथ ही, आपका कोड रखरखाव अत्यधिक जटिल होगा, आपके कोड में कोई भी सही दिखने वाला परिवर्तन आपके प्रोग्राम को तोड़ सकता है। आप कैसे याद रख सकते हैं या दूसरों के रखरखाव को याद रखने के लिए मजबूर कर सकते हैं? ऐसी जगहों पर चेतावनी डालना जहां ऐसे परिवर्तन हो सकते हैं? असंभव।

हां, तो निष्कर्ष: यह सिर्फ एक बुरा विचार है कि लेकिन सिरदर्द

+0

सैद्धांतिक रूप से, और कई व्यावहारिक मामलों में, 'std :: vector >' संकलित भी नहीं करता है। समझने की कोई बात नहीं आपकी मदद कर सकती है, जब मानक बस इसे मना करता है। – MSalters

+1

std :: vector > वीसी 9 में ठीक संकलित करता है, यह मानक-अनुरूप व्यवहार नहीं है? –

1

कुछ भी नहीं लाता कक्षाएं एक ऑटो ptr डेटा सदस्य है के लिए है, मैं हमेशा एक क्लोन विधि है कि एक नया ऑटो ptr देता है। मैं फिर एक असाइनमेंट विधि और कॉपी कन्स्ट्रक्टर को कार्यान्वित करता हूं जो क्लोन विधि को कॉल करता है (और कभी भी ऑटो पीआरटी का डिफॉल्ट असाइनमेंट ऑपरेटर नहीं)। इस तरह आप एसटीएल कंटेनरों में कक्षा का सुरक्षित रूप से उपयोग कर सकते हैं।