2009-09-10 11 views
26

boost::shared_ptr एक असामान्य निर्माताबूस्ट के shared_ptr (shared_ptr <Y> कॉन्स एंड आर, टी * पी) के लिए क्या उपयोग किया जाता है?

template<class Y> shared_ptr(shared_ptr<Y> const & r, T * p); 

है और मैं इस के लिए उपयोगी होगा क्या करने के लिए के रूप में एक छोटे से हैरान हूँ। असल में यह r के साथ स्वामित्व साझा करता है, लेकिन .get()p वापस करेगा। r.get()!

इसका मतलब है आप कुछ इस तरह कर सकते हैं:

int main() { 
    boost::shared_ptr<int> x(new int); 
    boost::shared_ptr<int> y(x, new int); 

    std::cout << x.get() << std::endl; 
    std::cout << y.get() << std::endl; 

    std::cout << x.use_count() << std::endl; 
    std::cout << y.use_count() << std::endl; 
} 

और तुम मिल जाएगा इस:

0x8c66008 
0x8c66030 
2 
2 

ध्यान दें कि संकेत अलग हैं, लेकिन वे दोनों 2 के एक use_count का दावा (चूंकि वे एक ही वस्तु के स्वामित्व साझा करते हैं)।

तो, intx के स्वामित्व में उपलब्ध नहीं होगा जब तक x रूप याy के आसपास है। और यदि मैं दस्तावेज़ों को सही समझता हूं, तो दूसरा int कभी विनाश नहीं होता है। मैं निम्नलिखित परीक्षण कार्यक्रम के साथ इस की पुष्टि की है:

struct T { 
    T() { std::cout << "T()" << std::endl; } 
    ~T() { std::cout << "~T()" << std::endl; } 
}; 

int main() { 
    boost::shared_ptr<T> x(new T); 
    boost::shared_ptr<T> y(x, new T); 

    std::cout << x.get() << std::endl; 
    std::cout << y.get() << std::endl; 

    std::cout << x.use_count() << std::endl; 
    std::cout << y.use_count() << std::endl; 
} 

यह outputs (अपेक्षित रूप से):

T() 
T() 
0x96c2008 
0x96c2030 
2 
2 
~T() 

तो ... क्या यह असामान्य निर्माण की उपयोगिता जो एक सूचक के स्वामित्व के शेयरों है , लेकिन का उपयोग करते समय एक और सूचक (जो इसका स्वामित्व नहीं है) की तरह कार्य करता है।

+7

अच्छा प्रश्न है। +1 – GManNickG

+3

टी एल; डॉ संस्करण: यह 'r' की एक उप-वस्तु के लिए एक सूचक बनाता है। –

उत्तर

29

यह उपयोगी है जब आप एक वर्ग के सदस्य और वर्ग का एक उदाहरण साझा करना चाहते हैं है पहले से ही एक shared_ptr है, निम्नलिखित की तरह:

struct A 
{ 
    int *B; // managed inside A 
}; 

shared_ptr<A> a(new A); 
shared_ptr<int> b(a, a->B); 

वे उपयोग गिनती और सामान को साझा करें। यह स्मृति उपयोग के लिए अनुकूलन है।

+1

एक अच्छा जवाब है। स्पष्ट रूप से, इस उदाहरण में, हम 'A' की वस्तु के रूप में लंबे समय के रूप' b' के आसपास है चारों ओर रखना चाहते हैं। मुझे लगता है कि हमारे पास एक विजेता है। –

+0

न केवल स्मृति उपयोग के लिए एक अनुकूलन, लेकिन विशिष्ट उदाहरण में, एक अलग दृष्टिकोण का उपयोग करके 'हटाएं (ए-> बी)' पर कॉल के साथ समाप्त हो जाएगा जो अप्रत्याशित हो सकता है ('struct A {int b;} पर विचार करें; shared_ptr a (नया ए); shared_ptr बी (ए, और ए-> बी) ') –

2

आपके पास कुछ ड्राइवर या निचले स्तर की एपीआई डेटा संरचना के लिए सूचक हो सकता है जो इसके निम्न स्तर एपीआई या अन्य माध्यमों द्वारा अतिरिक्त डेटा आवंटित कर सकता है। इस मामले में use_count को बढ़ाने में दिलचस्प हो सकता है लेकिन यदि पहले पॉइंटर अन्य डेटा पॉइंटर्स का मालिक होता है तो अतिरिक्त डेटा लौटाएं।

8

leiz's और piotr's जवाब पर विस्तार करने के लिए, shared_ptr<> 'अलियासिंग' इस विवरण एक WG21 कागज से है, "Improving shared_ptr for C++0x, Revision 2":

तृतीय। समर्थन अलियासिंग

उन्नत उपयोगकर्ताओं अक्सर एक shared_ptr उदाहरण p कि एक और (गुरु) shared_ptrq लेकिन अंकों के साथ स्वामित्व के शेयरों एक वस्तु है कि एक आधार *q की नहीं है करने के लिए बनाने के लिए क्षमता की आवश्यकता होती है। उदाहरण के लिए *p*q का सदस्य या तत्व हो सकता है।यह अनुभाग एक अतिरिक्त कन्स्ट्रक्टर का प्रस्ताव करता है जिसका उपयोग इस उद्देश्य के लिए किया जा सकता है।

सूचक क्षमता के इस वृद्धि की एक दिलचस्प दुष्प्रभाव यह है कि अब *_pointer_cast कार्यों उपयोगकर्ता कोड में लागू किया जा सकता है। make_shared कारखाने समारोह बाद में इस दस्तावेज़ में प्रस्तुत भी हो सकता है अलियासिंग निर्माता के माध्यम से ही सार्वजनिक shared_ptr के इंटरफ़ेस का उपयोग कर कार्यान्वित किया।

प्रभाव:

यह सुविधा एक पार्श्व-संगत तरीका है कि अपने अर्थपूर्ण शक्ति बढ़ जाती है और इसलिए दृढ़ता से C++ 0x मानक में जोड़े जाने की सिफारिश की है में shared_ptr के इंटरफेस का विस्तार । इसमें कोई स्रोत नहीं है- और बाइनरी संगतता समस्याएं।

प्रस्तावित पाठ:

में जोड़े shared_ptr [util.smartptr.shared] निम्नलिखित निर्माता:

template<class Y> shared_ptr(shared_ptr<Y> const & r, T * p); 

को [util.smartptr निम्नलिखित जोड़ें। shared.const]:

template<class Y> shared_ptr(shared_ptr<Y> const & r, T * p); 

प्रभाव: एक shared_ptr उदाहरण है किr साथ p और शेयरों स्वामित्व संग्रहीत करता है निर्माण करती है।

पोस्टकंडिशन:get() == p && use_count() == r.use_count()

फेंकता है: कुछ भी नहीं।

[नोट: एक dangling सूचक की संभावना से बचने के लिए, यह निर्माता के उपयोगकर्ता सुनिश्चित करना चाहिए कि p मान्य कम से कम रहता है जब तक r के स्वामित्व समूह नष्ट हो जाता है। --end टिप्पणी]

[ध्यान दें:। यह निर्माता अरिक्त संग्रहीत सूचक के साथ एक खालीshared_ptr उदाहरण बना सकते हैं। --end टिप्पणी।]

4

आप भी इस का उपयोग कर सकते गतिशील casted संकेत रखने के लिए है, अर्थात:

class A {}; 
class B: public A {}; 

shared_ptr<A> a(new B); 
shared_ptr<B> b(a, dynamic_cast<B*>(a.get())); 
+0

एक और दिलचस्प उपयोग जो स्पष्ट रूप से "एलियासिंग" श्रेणी में आता है। अच्छी बात। –

0

के लिए "shared_ptr<B> b(a, dynamic_cast<B*>(a.get()));"

मुझे लगता है कि यह स्मार्ट सूचक उपयोग करने की सिफारिश तरीका नहीं है।

इस प्रकार के रूपांतरण करने की सिफारिश की जिस तरह से किया जाना चाहिए:

shared_ptr<B> b(a); 

के बाद से बूस्ट दस्तावेज़ में यह उल्लेख किया गया है कि:

shared_ptr<T> परोक्ष shared_ptr<U> जब भी टी * कर सकते हैं करने के लिए परिवर्तित किया जा सकता है स्पष्ट रूप से यू * में परिवर्तित हो। विशेष रूप से, shared_ptr<T> परोक्ष shared_ptr<T> const, के लिए परिवर्तनीय shared_ptr<U> है जहां यू टी के एक सुलभ आधार है, और shared_ptr<void> करने के लिए।

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

0

मैं अपनी छोटी पुस्तकालय में उपयोग में shared_ptr के अलियासिंग निर्माता डाल दिया है:

http://code.google.com/p/infectorpp/ (बस अपना सरल आईओसी कंटेनर)

मुद्दा यह है कि एक से वापस करने के बाद से मैं ज्ञात प्रकार का एक shared_ptr की जरूरत है पॉलिमॉर्फिक वर्ग (जो कि प्रकार को नहीं जानता)। मैं share_ptr को जिस प्रकार की आवश्यकता थी, उसमें पूरी तरह से रूपांतरित करने में सक्षम नहीं था।

फ़ाइल "InfectorHelpers.hpp" (लाइन 72-99) आप देख सकते हैं कि प्रकार IAnyShared के लिए कार्रवाई में हैं।

एलिसिंग कन्स्ट्रक्टर share_ptr बनाता है जो पॉइंटर्स को वास्तव में इंगित नहीं करता है, लेकिन वे मूल ऑब्जेक्ट में संदर्भ काउंटर बढ़ाते हैं और यह बहुत उपयोगी हो सकता है।

मूल रूप से आप aliasing निर्माता और एक संदर्भ काउंटर के रूप में यह खतरा का उपयोग कर कुछ भी करने के लिए एक सूचक बना सकते हैं।

//my class 
std::shared_ptr<T> ist; 
int a; //dummy variable. I need its adress 

virtual std::shared_ptr<int> getReferenceCounter(){ 
    return std::shared_ptr<int>(ist,&a); //not intended for dereferencing 
} 

virtual void* getPtr(); //return raw pointer to T 

अब हम अलियासिंग निर्माता के साथ कुछ बनाने के लिए, के लिए पर्याप्त डेटा दोनों "एक संदर्भ काउंटर" और टी के एक सहायता करने के लिए एक सूचक है

std::shared_ptr<T> aPtr(any->getReferenceCounter(), //share same ref counter 
       static_cast<T*>(any->getPtr())); //potentially unsafe cast! 

मैं नाटक नहीं करते इस आविष्कार करने का एलियासिंग कन्स्ट्रक्टर के लिए उपयोग करें, लेकिन मैंने कभी किसी और को ऐसा नहीं देखा। यदि आप अनुमान लगा रहे हैं कि क्या गंदा कोड काम करता है तो जवाब हाँ है।

संबंधित मुद्दे