2013-07-04 12 views
29

पर अद्वितीय_ptr मैं एक फ्रेम में व्युत्पन्न कक्षा में unique_ptr का उपयोग करने की कोशिश कर रहा हूं जो बेस क्लास में unique_ptr लेता है। कुछ की तरह:एक बेस क्लास

class Base 
{}; 

class Derived : public Base 
{}; 

void f(unique_ptr<Base> const &base) 
{} 

… 

unique_ptr<Derived> derived = unique_ptr<Derived>(new Derived); 
f(derived); 

अगर मैं this answer सही ढंग से समझ, इस कोड को काम करना चाहिए, लेकिन यह निम्न संकलन त्रुटियों का कारण बनता: ​​

त्रुटि C2664: 'म': 'एसटीडी से पैरामीटर 1 परिवर्तित नहीं कर सकते: : unique_ptr < _Ty> स्थिरांक एसटीडी 'को' :: unique_ptr < _Ty> & '

IntelliSense: "एसटीडी से कोई उपयुक्त उपयोगकर्ता परिभाषित रूपांतरण :: unique_ptr < व्युत्पन्न, std :: default_delete < डेर ived >> "से" स्थिरांक std :: < बेस unique_ptr, std :: default_delete < बेस >> "मौजूद है

अगर मैं f बदलने unique_ptr<Derived> const &derived लेने के लिए, यह ठीक काम करता है, लेकिन यह नहीं है कि मैं क्या चाहता हूँ।

क्या मैं कुछ गलत कर रहा हूं? मैं इसके आसपास काम करने के लिए क्या कर सकता हूं?

मैं दृश्य स्टूडियो 2012

उत्तर

39

उपयोग कर रहा हूँ आप तीन विकल्प हैं:

  1. स्वामित्व दे। फ़ंक्शन कॉल के बाद यह गतिशील ऑब्जेक्ट तक पहुंच के बिना आपके स्थानीय चर को छोड़ देगा; वस्तु कॉल प्राप्त करने वाला को हस्तांतरित कर दिया गया है

    f(std::move(derived)); 
    
  2. बदलें f के हस्ताक्षर:

    void f(std::unique_ptr<Derived> const &); 
    
  3. बदलें अपने चर के प्रकार:

    std::unique_ptr<base> derived = std::unique_ptr<Derived>(new Derived); 
    

    या निश्चित रूप से बस:

    std::unique_ptr<base> derived(new Derived); 
    

    या भी:

    std::unique_ptr<base> derived = std::make_unique<Derived>(); 
    
  4. अद्यतन: स्वामित्व या, जैसा कि टिप्पणी में सिफारिश की, स्थानांतरित नहीं होते बिल्कुल:

    void f(Base & b); 
    
    f(*derived); 
    
+1

उस स्थिति में, मैं 4 के साथ जाने पर विचार कर रहा हूं। 'Shared_ptr' का उपयोग करें। – svick

+2

फ़ंक्शन कॉल के लिए एक अद्वितीय_ptr के बजाय केवल संदर्भ का उपयोग करने के बारे में कैसे? – ltjax

+5

@ एसविक, फ़ंक्शन में स्मार्ट पॉइंटर में क्यों गुजरता है यदि यह सूचक का स्वामित्व नहीं लेता है? स्मार्ट पॉइंटर्स के लिए यह नहीं है। –

8

एक संभव समाधान बदलने के लिए है Base const* होने के लिए तर्क का प्रकार, और इसके बजाय derived.get() पास करें। unique_ptr const<Base>& (और unique_ptr संशोधित नहीं किया जा रहा है) के साथ स्वामित्व का कोई हस्तांतरण नहीं है, इसलिए Base const* में बदलना अर्थ नहीं बदलता है।


हर्ब Sutter Smart Pointer Parameters में विस्तार से स्मार्ट सूचक तर्क गुजर चर्चा करता है।लिंक किए गए लेख से एक उद्धरण इस सटीक स्थिति को दर्शाता है: क्योंकि यह स्वीकार कर सकते हैं एक const unique_ptr<widget>&

पासिंग अजीब बात है केवल या तो null या एक widget जिसका जीवनकाल होता है एक unique_ptr के माध्यम से बुला कोड में प्रबंधित किया, और कॉल प्राप्त करने वाला आम तौर पर कॉलर के जीवनकाल प्रबंधन विकल्प की परवाह नहीं करनी चाहिए। widget* पास करने से इन मामलों के सख्त सुपरसैट को शामिल किया गया है और कॉलर का उपयोग होने वाली आजीवन नीति के बावजूद "null या widget" स्वीकार कर सकते हैं।

+0

'बेस कॉन्स्ट *' का अर्थ यह नहीं है कि फ़ंक्शन कहीं पॉइंटर को स्टोर कर सकता है? हालांकि स्मार्ट पॉइंटर्स इससे बचने की कोशिश कर रहे हैं। – svick

+0

@ एसविक, फ़ंक्शन 'base.get() 'को आसानी से स्टोर कर सकता है (' get() '' const' सदस्य फ़ंक्शन है)। – hmjd

+0

@ एसविक नंबर स्मार्ट पॉइंटर्स स्पष्ट करने के द्वारा मेमोरी लीक से बचने के लिए हैं कि किसी ऑब्जेक्ट का स्वामी कौन है। यदि आप किसी फ़ंक्शन के लिए तर्क के रूप में कच्चे सूचक को पास करते हैं तो आप इसे पढ़ने/संशोधित करने के लिए पहुंच प्रदान करते हैं। स्मार्ट पॉइंटर्स कच्चे 'नए 'और' डिलीट 'का उपयोग करने से बचने के लिए हैं, पॉइंटर्स बिल्कुल नहीं। – etam1024