std :: इसे साझा किया गया


101

मैं वर्तमान में सीखने की कोशिश कर रहा हूं कि स्मार्ट पॉइंटर्स का उपयोग कैसे किया जाए। हालाँकि कुछ प्रयोग करते समय मैंने निम्नलिखित स्थिति की खोज की जिसके लिए मुझे कोई समाधान नहीं मिला:

कल्पना कीजिए कि आपके पास कक्षा ए की एक वस्तु है जो कक्षा बी (बच्चे) की वस्तु का माता-पिता है, लेकिन दोनों को एक दूसरे को जानना चाहिए:

class A;
class B;

class A
{
public:
    void addChild(std::shared_ptr<B> child)
    {
        children->push_back(child);

        // How to do pass the pointer correctly?
        // child->setParent(this);  // wrong
        //                  ^^^^
    }

private:        
    std::list<std::shared_ptr<B>> children;
};

class B
{
public:
    setParent(std::shared_ptr<A> parent)
    {
        this->parent = parent;
    };

private:
    std::shared_ptr<A> parent;
};

सवाल यह है कि कक्षा ए की वस्तु अपने बच्चे के लिए std::shared_ptrस्वयं ( this) का पास कैसे हो सकती है ?

बूस्ट शेयर्ड पॉइंटर्स ( फॉर boost::shared_ptrthis फॉरिंग ) के लिए समाधान हैं , लेकिन std::स्मार्ट पॉइंटर्स का उपयोग करके इसे कैसे संभालें ?


2
जैसा कि किसी अन्य उपकरण के साथ होता है, जब आपको उचित लगे तब इसका उपयोग करना होगा। तुम क्या कर रहे हैं के लिए स्मार्ट संकेत का उपयोग करना है नहीं
YePhIcK

इसी तरह बढ़ावा देने के लिए। देखें यहाँ
जुआनकोपंजा

1
यह अमूर्त के स्तर पर एक समस्या है। आप यह भी नहीं जानते कि "यह" ढेर पर स्मृति को इंगित करता है।
वॉन काटो

ठीक है, भाषा नहीं है, लेकिन आप करते हैं। जब तक आप क्या है का ट्रैक रखते हैं, तो आप ठीक हो जाएंगे।
एलेक्स

जवाबों:


168

नहीं है std::enable_shared_from_thisतो बस इस उद्देश्य के लिए। आपको इससे विरासत मिलती है और आप .shared_from_this()कक्षा के अंदर से कॉल कर सकते हैं । इसके अलावा, आप यहां परिपत्र निर्भरता पैदा कर रहे हैं जिससे संसाधन लीक हो सकते हैं। के उपयोग से इसका समाधान किया जा सकता है std::weak_ptr। तो आपका कोड इस तरह दिख सकता है (यह मानते हुए कि बच्चे माता-पिता के अस्तित्व पर भरोसा करते हैं, न कि दूसरे तरीके से):

class A;
class B;

class A
    : public std::enable_shared_from_this<A>
{
public:
    void addChild(std::shared_ptr<B> child)
    {
        children.push_back(child);

        // like this
        child->setParent(shared_from_this());  // ok
        //               ^^^^^^^^^^^^^^^^^^
    }

private:     
    // note weak_ptr   
    std::list<std::weak_ptr<B>> children;
    //             ^^^^^^^^
};

class B
{
public:
    void setParent(std::shared_ptr<A> parent)
    {
        this->parent = parent;
    }

private:
    std::shared_ptr<A> parent;
};

हालाँकि, ध्यान दें कि कॉलिंग के .shared_from_this()लिए कॉल के बिंदु पर thisस्वामित्व होना आवश्यक है std::shared_ptr। इसका मतलब है कि आप स्टैक पर ऐसी कोई वस्तु नहीं बना सकते हैं, और आम तौर पर.shared_from_this() एक निर्माता या विध्वंसक के भीतर से कॉल नहीं कर सकते हैं ।


1
आपके स्पष्टीकरण के लिए और मेरी परिपत्र निर्भरता समस्या को इंगित करने के लिए धन्यवाद।
इकारस

@ डीडुलेटर का क्या मतलब है?
यूरी किलोचेक

shared_ptrडिफॉल्ट-कंस्ट्रक्ट के आधार पर निर्माण करने की कोशिश करें shared_ptrऔर जो भी आप इसे इंगित करना चाहते हैं ...
Deduplicator

1
@Deduplicator यह एक, मेरी सजा को माफ करता है, बल्कि व्यर्थ साझा सूचक है। उस निर्माणकर्ता को प्रबंधित ऑब्जेक्ट या उसके ठिकानों के सदस्यों के लिए पॉइंटर्स के साथ उपयोग करने का इरादा है। किसी भी मामले में आपकी बात क्या है (मुझे क्षमा करें)? ये गैर-स्वामी shared_ptrएस इस सवाल के लिए अप्रासंगिक हैं। shared_from_thisपूर्व शर्त स्पष्ट रूप से बताती है कि shared_ptrकॉल के बिंदु पर कुछ के द्वारा वस्तु का स्वामित्व होना चाहिए (न कि केवल बताया गया) ।
यूरी किलोचेक

1
shared_ptrकॉल के बिंदु पर @kazarey स्वामित्व आवश्यक है, लेकिन एक विशिष्ट उपयोग पैटर्न में, यानी कुछ ऐसा shared_ptr<Foo> p(new Foo());, जैसे shared_ptrकि यह पूरी तरह से निर्मित होने के बाद ही किसी वस्तु के स्वामित्व को मानता है। इसे shared_ptrकंस्ट्रक्टर द्वारा बनाकर thisऔर इसे गैर-स्थानीय (जैसे एक संदर्भ तर्क में) स्टोर करके बनाया गया है, इसे दरकिनार करना संभव है, इसलिए जब कंस्ट्रक्टर पूरा हो जाता है तो यह मर नहीं जाता है। लेकिन इस जटिल परिदृश्य की आवश्यकता होने की संभावना नहीं है।
यूरी किलोचेक

9

आपके डिजाइन में कई समस्याएं हैं, जो आपको स्मार्ट पॉइंटर्स की गलतफहमी से उपजी हैं।

स्मार्ट पॉइंटर्स का उपयोग स्वामित्व घोषित करने के लिए किया जाता है। आप यह घोषित करके इसे तोड़ रहे हैं कि दोनों माता-पिता सभी बच्चों के मालिक हैं, लेकिन यह भी कि प्रत्येक बच्चे का अपना माता-पिता है। दोनों सत्य नहीं हो सकते।

इसके अलावा, आप एक कमजोर पॉइंटर को वापस कर रहे हैं getChild()। ऐसा करके, आप घोषणा कर रहे हैं कि कॉलर को स्वामित्व की परवाह नहीं करनी चाहिए। अब यह बहुत सीमित हो सकता है, लेकिन ऐसा करने से, आपको यह सुनिश्चित करना चाहिए कि प्रश्न में मौजूद बच्चा नष्ट नहीं होगा, जबकि कोई भी कमजोर बिंदु अभी भी पकड़ में है, यदि आप एक स्मार्ट पॉइंटर का उपयोग करते हैं, तो यह अपने आप हल हो जाएगा ।

और अंतिम बात। आमतौर पर, जब आप नई संस्थाओं को स्वीकार कर रहे होते हैं, तो आपको आमतौर पर कच्चे पॉइंटर्स को स्वीकार करना चाहिए। माता-पिता के बीच बच्चों की अदला-बदली के लिए स्मार्ट पॉइंटर का अपना अर्थ हो सकता है, लेकिन सामान्य उपयोग के लिए, आपको कच्चे पॉइंटर्स को स्वीकार करना चाहिए।


ऐसा लगता है कि मुझे वास्तव में स्मार्ट पॉइंटर्स की अपनी समझ को स्पष्ट करने की आवश्यकता है। उसे इंगित करने के लिए धन्यवाद।
इकारस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.