c++ - सी++ प्रोग्राम्स




कैसे बढ़ा सकते हैं:: सीरियलाइजेशन का उपयोग सीडी+साझा_पीआर से सी++ 11 से किया जा सकता है? (5)

मुझे पता है कि boost::shared_ptr serialization के लिए बूस्ट मॉड्यूल है , लेकिन मुझे std::shared_ptr लिए कुछ भी नहीं मिल रहा है।

साथ ही, मुझे नहीं पता कि इसे आसानी से कैसे कार्यान्वित किया जाए। मुझे डर है कि निम्नलिखित कोड

namespace boost{namespace serialization{
template<class Archive, class T>
inline void serialize(Archive & ar, std::shared_ptr<T> &t, const unsigned int version)
{
  if(Archive::is_loading::value) {T*r;ar>>r;t=r;}
  else {ar<<t.get();}
}
}}//namespaces

काम नहीं करता दरअसल, अगर कुछ ऑब्जेक्ट को कई बार संदर्भित किया गया था, तो इसे ar>>r पहले भाग से लोड किया जाएगा, और उसके बाद केवल एक सूचक की प्रतिलिपि बनाई जाएगी। हालांकि हम इसे इंगित करने वाले एकाधिक shared_ptr ऑब्जेक्ट्स बनाएंगे, और इसलिए इसे एक से अधिक बार नष्ट कर देंगे।

उस पर कोई विचार?

मैं जिस सिस्टम का उपयोग कर रहा हूं उसके बारे में कुछ तकनीकी विवरण:

  • ओएस: उबंटू 11.10 (x64)
  • कंपाइलर: जी ++ (उबंटू / लिनारो 4.6.1-9ubuntu3) 4.6.1
  • बूस्ट संस्करण: 1.46.1 (सुडो sudo apt-get install libboost-dev )

अरे दोस्तों ने आखिरकार बूस्ट सीरियलाइजेशन का उपयोग करके std :: shared_ptr को क्रमबद्ध करने के तरीके पर एक समाधान पाया। आपको केवल कोड का निम्नलिखित भाग चाहिए (स्पष्टीकरण निम्नानुसार है):

#include <boost/serialization/split_free.hpp>
#include <boost/unordered_map.hpp>

//---/ Wrapper for std::shared_ptr<> /------------------------------------------

namespace boost { namespace serialization {

template<class Archive, class Type>
void save(Archive & archive, const std::shared_ptr<Type> & value, const unsigned int /*version*/)
{
    Type *data = value.get();
    archive << data;
}

template<class Archive, class Type>
void load(Archive & archive, std::shared_ptr<Type> & value, const unsigned int /*version*/)
{
    Type *data;
    archive >> data;

    typedef std::weak_ptr<Type> WeakPtr;
    static boost::unordered_map<void*, WeakPtr> hash;

    if (hash[data].expired())
    {
         value = std::shared_ptr<Type>(data);
         hash[data] = value;
    }
    else value = hash[data].lock();
}

template<class Archive, class Type>
inline void serialize(Archive & archive, std::shared_ptr<Type> & value, const unsigned int version)
{
    split_free(archive, value, version);
}

}}

यह कोड फ़ंक्शन सेव () में std :: shared_ptr द्वारा प्रबंधित ऑब्जेक्ट को बस क्रमबद्ध करता है। यदि एकाधिक std :: shared_ptr उदाहरण एक ही ऑब्जेक्ट को इंगित करते हैं तो बूस्ट सीरियलाइजेशन स्वचालित रूप से इसे केवल एक बार स्टोर करने की देखभाल करेगा। जादू लोड () में होता है जहां बूस्ट सीरियलाइजेशन ऑब्जेक्ट (डेटा) में कच्चे सूचक को लौटाता है। यह कच्चा सूचक एक हैश में देखा जाता है जिसमें प्रत्येक कच्चे सूचक के लिए कमजोर_प्टर होता है। यदि हैश में कमजोर_पीआरआर की समयसीमा समाप्त हो गई है तो हम सुरक्षित रूप से एक नया साझा_पीटीआर उदाहरण बना सकते हैं, इसे कच्चे पॉइंटर को प्रबंधित करने और हैश में कमजोर_प्टर स्टोर करने दें। अगर कमजोर_पीआरआर की समयसीमा समाप्त नहीं होती है तो हम इसे एक साझा_पीटीआर वापस करने के लिए बस लॉक करते हैं। इस तरह संदर्भ गणना सही है।


आपने यह नहीं कहा है कि "काम नहीं करता" का अर्थ क्या है; यह संकलित नहीं करता है? यह मूल्य को सही तरीके से लोड / स्टोर नहीं करता है? यह नहीं है .. क्या?

यहां दो समस्याएं हैं जिन्हें मैं यहां पहचान सकता हूं, हालांकि आपका जानबूझकर डिज़ाइन का हिस्सा हो सकता है।

सबसे पहले, आपने लोड प्रक्रिया में सही पॉइंटर नहीं बनाया है। आइए इसे तोड़ दें:

inline void serialize(Archive & ar, std::shared_ptr<T> &t, const unsigned int version) {
    if (1) { //unimportant
        T* r;
        ar >> r;
        t = r;
    }
}

जब आप std :: shared_ptr का ऑब्जेक्ट करते हैं, तो आप पॉइंटर जैसी क्षमता प्रदान करने के लिए क्लास टेम्पलेट को तत्काल कर रहे हैं (जैसा कि आप जानते हैं)। यदि आप एक int के साथ बनाया है, तो यह एक int सूचक के रूप में काम करेगा। हालांकि, बस प्रकार को टी के रूप में पास करने का मतलब यह नहीं है कि उस प्रकार का बनाया गया पॉइंटर स्वचालित रूप से उस टेम्पलेट का उपयोग करेगा; वास्तव में, आप टी * आर के साथ एक नंगे सूचक बना रहे हैं। यह भी int * आर हो सकता है। फिर आप इसे नए से शुरू करने में असफल हो जाते हैं; आर कहीं भी इशारा कर सकता है। यदि इसे नए के साथ ठीक से इंटिलाइज किया गया था, तो आपको उस ऑब्जेक्ट के सृजन / हटाने के लिए सही संदर्भ गिनती मिल सकती है; यह एक ऐसा क्षेत्र है जहां std :: shared_ptr मेरे लिए प्रयास के लायक नहीं लगता है। मुझे लगता है कि एक नंगे सूचक से असाइनमेंट दूसरे संदर्भ के रूप में गिना जाता है, पहले नहीं, लेकिन मैं गलत हो सकता हूं? किसी भी तरह, यह समस्या नहीं है। आप शायद ढेर को भ्रष्ट कर रहे हैं; एक कंपाइलर को एक अनियंत्रित सूचक का उपयोग करने के बारे में चेतावनी थूकना चाहिए, यह आश्चर्य की बात नहीं है। मुझे उम्मीद है कि आपके पास चेतावनी बंद नहीं है।

अगर मुझे सही याद है, तो आर की घोषणा को प्रतिस्थापित करने की जरूरत है:

std::shared_ptr<T> r = new std::shared_ptr<T>;

हालांकि यह हो सकता है

std::shared_ptr<T> r = new std::shared_ptr<T>(r());

मैंने थोड़ी देर के लिए shared_ptr का उपयोग नहीं किया है।

वैसे, टीआर 1, कम से कम 2 साल से बाहर हो गया है। यह बूस्ट के shared_ptr से आधारित है। मुझे नहीं पता कि आप बूस्ट 1.46 का उपयोग क्यों कर रहे हैं, लेकिन मुझे लगता है कि यह उस समय से बाहर था जब shared_ptr मानक का हिस्सा बन गया था? तो यह संगत होना चाहिए ...?

किसी भी तरह, दूसरी संभावित त्रुटि के साथ आता है

t = r;

मुझे लगता है - गलत तरीके से? - कि आप इसे पुन: असाइन करके संदर्भ गणना को कम करने के लिए चाहते हैं (और संभवतः ऑब्जेक्ट टी पॉइंट को नष्ट करना)। यदि आप इसे कॉपी करना चाहते हैं, तो आप निश्चित रूप से उपयोग करेंगे:

*t = *r;

और सुनिश्चित करें कि आपकी प्रतिलिपि निर्माता ठीक से काम करता है।


बूस्ट सीरियलाइजेशन के हाल के संस्करणों में सभी मानक लाइब्रेरी स्मार्ट पॉइंटर्स के लिए समर्थन शामिल है।


यह डेनिम के समाधान में सुधार है, जो साझा_ptr लोड करने का समर्थन करता है जो एक ही स्मृति को इंगित करता है, लेकिन विभिन्न प्रकार के साथ। यह समस्या तब प्रकट हो सकती है जब संग्रह एक ही समय में shared_ptr और shared_ptr होता है जो एक ही ऑब्जेक्ट को इंगित कर रहे हैं, जहां ए को बी से विरासत में मिला है।

namespace boost {
namespace serialization {

    template<class Archive, class Type>
    void save(Archive & archive, const std::shared_ptr<Type> & value, const unsigned int /*version*/)
    {
        Type *data = value.get();
        archive << data;
    }

    static std::map<void*, std::weak_ptr<void>> hash;

    template<class Archive, class Type>
    void load(Archive & archive, std::shared_ptr<Type> & value, const unsigned int /*version*/)
    {
        Type *data;
        archive >> data;

        if (hash[data].expired())
        {
            std::shared_ptr<void> ptr(data);
            value = static_pointer_cast<Type>(ptr);
            hash[data] = ptr;
        }
        else value = static_pointer_cast<Type>(hash[data].lock());
    }

    template<class Archive, class Type>
    inline void serialize(Archive & archive, std::shared_ptr<Type> & value, const unsigned int version)
    {
        split_free(archive, value, version);
    }

}}

इस अहसास की कमजोरी के रूप में - एक विशाल मानचित्र।


सीरियलाइजेशन को मानक लाइब्रेरी द्वारा बढ़ावा दिया जाता है और नहीं, हालांकि shared_ptr मानक में शामिल है, यह टीआर 1 (तकनीकी रिपोर्ट 1) का हिस्सा है।

टीआर 1 के रूप में अब serialization नहीं है। इसलिए मैं अनुशंसा करता हूं कि आप बूस्ट के साझा सूचक का उपयोग करें।





boost-serialization