2010-07-16 10 views
26

मैं कोड के एक अनुभाग पर काम कर रहा हूं जिसमें कई संभावित विफलता बिंदु हैं जो इसे जल्दी से कार्य से बाहर निकलने का कारण बनते हैं। जिस पुस्तकालयों के साथ मैं बातचीत कर रहा हूं, उसके लिए आवश्यक है कि सी-स्टाइल सरणी कार्यों को पारित की जाए। तो, बजाय हर निकास बिंदु पर पहुंच सरणियों पर हटाना बुलाने की, मैं यह कर रहा हूँ:क्या आप सी-स्टाइल सरणी के RAII के लिए shared_ptr का उपयोग कर सकते हैं?

void SomeFunction(int arrayLength) 
{ 
    shared_ptr<char> raiiArray(new char[arrayLength]); 
    pArray = raiiArray.get(); 

    if(SomeFunctionThatRequiresCArray(pArray) == FAILED) { return; } 

    //etc. 
} 

मैं unique_ptr, उपयोग करना चाहता था लेकिन मेरे वर्तमान संकलक इसका समर्थन नहीं करता और संदर्भ गिनती भूमि के ऊपर नहीं है वास्तव में इस मामले में कोई फर्क नहीं पड़ता।

मैं सोच रहा हूं कि विरासत कोड के साथ इंटरफेसिंग करते समय किसी के पास इस अभ्यास पर कोई विचार है या नहीं।

अद्यतन मैं पूरी तरह से shared_ptrdelete [] के बजाय delete बुला के बारे में भूल गया था। मैंने अभी कोई स्मृति रिसाव नहीं देखा और इसके साथ जाने का फैसला किया। एक वेक्टर का उपयोग करने के लिए भी सोचा नहीं था। चूंकि मैं हाल ही में (मेरे लिए) सी ++ में डीलिंग कर रहा हूं, मुझे लगता है कि मुझे लगता है कि "यदि आपके पास एकमात्र उपकरण है तो एक हथौड़ा है, सबकुछ एक नाखून जैसा दिखता है।" सिंड्रोम। प्रतिक्रिया के लिए धन्यवाद।

UPDATE2 मुझे लगा कि मैं सवाल बदलूंगा और इसे एक ही गलती करने वाले व्यक्ति के लिए थोड़ा और मूल्यवान बनाने का उत्तर प्रदान करूंगा। हालांकि वहां scoped_array, shared_array और vector की तरह विकल्प हैं, आप एक shared_ptr का उपयोग एक सरणी के दायरे का प्रबंधन कर सकते हैं (लेकिन इस के बाद मुझे पता नहीं क्यों मुझे चाहेगा है):

template <typename T> 
    class ArrayDeleter 
    { 
    public: 
     void operator() (T* d) const 
     { 
      delete [] d; 
     } 
    }; 

void SomeFunction(int arrayLength) 
    { 
     shared_ptr<char> raiiArray(new char[arrayLength], ArrayDeleter<char>()); 
     pArray = raiiArray.get(); 

     if(SomeFunctionThatRequiresCArray(pArray) == FAILED) { return; } 

     //etc. 
    } 
+1

नाइटपिकिंग: [[shared_ptr]] गतिशील सरणी पॉइंटर्स पर सही ढंग से काम नहीं करता है। [[scoped_array]] या [[shared_array]] का उपयोग करें। इस मामले में – rwong

उत्तर

27

गतिशील आवंटित सरणी के लिए पॉइंटर्स को पकड़ने के लिए shared_ptr या scoped_ptr का उपयोग न करें। share_ptr और scoped_ptr delete ptr; का उपयोग क्लीन-अप करने के लिए करें जब पॉइंटर का अब संदर्भित नहीं किया जाता है/स्कोप से बाहर चला जाता है, जिसने गतिशील आवंटित सरणी पर अपरिभाषित व्यवहार का आह्वान किया। इसके बजाय, share_array या scoped_array का उपयोग करें, जो विनाशकारी होने पर delete[] ptr; का सही ढंग से उपयोग करें।

अपने प्रश्न का उत्तर देने के लिए, यदि आप स्मार्ट पॉइंटर को पास करने वाले नहीं हैं, तो scoped_array का उपयोग करें, क्योंकि shared_array से कम ओवरहेड है।

वैकल्पिक रूप से, std::vector का उपयोग सरणी भंडारण के रूप में करें (वैक्टरों ने संगत स्मृति आवंटन की गारंटी दी है)।

+7

डिफ़ॉल्ट रूप से, shared_ptr और scoped_ptr पीटीआर को हटाते हैं, लेकिन आप अपना खुद का डिलीटर फ़ंक्शन या फ़ैक्टर प्रदान कर सकते हैं। – George

5

इस के लिए boost::scoped_ptr है।

+7

scoped_array –

+0

हाँ, निश्चित रूप से, वे दोनों वहाँ हैं। धन्यवाद। –

15

boost::scoped_array का उपयोग करें, या बेहतर std::vector यदि आप किसी सरणी से निपट रहे हैं।

3

यह

shared_ptr<char*> raiiArray(new char[arrayLength]); 

एक अच्छा अभ्यास नहीं है, लेकिन, अपरिभाषित व्यवहार का कारण बनता है के रूप में आप ऑपरेटर new[] साथ आवंटित है, लेकिन shared_ptroperator delete का उपयोग करता है स्मृति मुक्त करने के लिए। उपयोग करने के लिए सही बात boost::shared_array है या एक कस्टम डिलीटर जोड़ें।

7

मैं अत्यधिक std::vector का उपयोग करके अत्यधिक अनुशंसा करता हूं। vectors में तत्व ढेर पर आवंटित किए जाते हैं, और हटाए जाएंगे जब vector गुंजाइश से बाहर हो जाता है, जहां भी आप फ़ंक्शन से बाहर निकलते हैं।

सी-स्टाइल सरणी की आवश्यकता वाले विरासत कोड पर vector पास करने के लिए, बस &vectorName[0] पास करें। तत्व स्मृति में संगत होने की गारंटी दी जाती है।

+0

सुनिश्चित करें कि वेक्टर नाम 'और वेक्टरनाम [0]' या 'और vectorName.front() 'का उपयोग करने से पहले वेक्टर खाली नहीं है, क्योंकि यह कुछ कार्यान्वयन के लिए अपरिभाषित या व्यवहार करने के लिए जोर दे रहा है। – AshleysBrain

6

के लिए सी ++ 11 उपयोगकर्ता कुछ टिप्पणी:

shared_ptr के लिए, वहाँ सी ++ 11 सरणी प्रकार <memory> और मानक अनुरूप (अंतिम मसौदा WRT) में परिभाषित के लिए एक डिफ़ॉल्ट Deleter में है, इसलिए यह किया जा सकता है

std::shared_ptr<char> raiiArray(new char[arrayLength], std::default_delete<char[]>()); 

सी ++ 11 new[] और delete[] से निपटने के लिए एक आंशिक विशेषज्ञता है में unique_ptr: इस तरह के मामलों के लिए अतिरिक्त फैंसी deleters बिना। लेकिन दुर्भाग्यवश, इसमें साझा व्यवहार नहीं है। एक अच्छा कारण होना चाहिए shared_ptr के लिए ऐसी कोई विशेषज्ञता नहीं है, लेकिन यदि आप इसे जानते हैं, तो मैंने इसे नहीं देखा, कृपया इसे साझा करें।

+1

[इस SO उत्तर] के अनुसार (http://stackoverflow.com/a/8947700/1094609), अंतिम कारण 'shared_ptr' के लिए कोई सरणी विशेषज्ञता नहीं है कि "[टी] यहां कभी भी एक वास्तविक लिखित प्रस्ताव नहीं था ऐसा करने के लिए एलडब्ल्यूजी का। " –