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




सी++ प्रोग्राम्स (6)

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

मुझे पता है कि 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 )

यह साझा पॉइंटर हेडर जैसे <boost/serialization/shared_ptr.hpp> आधार पर अपने आप को रोल करने का परिणाम है।

बस एक हेडर फ़ाइल में नीचे कॉपी और पेस्ट करें और इसे शामिल करें:

#ifndef BOOST_SERIALIZATION_STD_SHARED_PTR_HPP
#define BOOST_SERIALIZATION_STD_SHARED_PTR_HPP

// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif

/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// shared_ptr.hpp: serialization for boost shared pointer

// (C) Copyright 2004 Robert Ramey and Martin Ecker
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org for updates, documentation, and revision history.

#include <cstddef> // NULL

#include <boost/config.hpp>
#include <boost/mpl/integral_c.hpp>
#include <boost/mpl/integral_c_tag.hpp>

#include <boost/detail/workaround.hpp>
#include <memory>

#include <boost/serialization/split_free.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/version.hpp>
#include <boost/serialization/tracking.hpp>

/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// shared_ptr serialization traits
// version 1 to distinguish from boost 1.32 version. Note: we can only do this
// for a template when the compiler supports partial template specialization

#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
    namespace boost {
    namespace serialization{
        template<class T>
        struct version< ::std::shared_ptr< T > > {
            typedef mpl::integral_c_tag tag;
            #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206))
            typedef BOOST_DEDUCED_TYPENAME mpl::int_<1> type;
            #else
            typedef mpl::int_<1> type;
            #endif
            #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570))
            BOOST_STATIC_CONSTANT(int, value = 1);
            #else
            BOOST_STATIC_CONSTANT(int, value = type::value);
            #endif
        };
        // don't track shared pointers
        template<class T>
        struct tracking_level< ::std::shared_ptr< T > > {
            typedef mpl::integral_c_tag tag;
            #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206))
            typedef BOOST_DEDUCED_TYPENAME mpl::int_< ::boost::serialization::track_never> type;
            #else
            typedef mpl::int_< ::boost::serialization::track_never> type;
            #endif
            #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570))
            BOOST_STATIC_CONSTANT(int, value = ::boost::serialization::track_never);
            #else
            BOOST_STATIC_CONSTANT(int, value = type::value);
            #endif
        };
    }}
    #define BOOST_SERIALIZATION_SHARED_PTR(T)
#else
    // define macro to let users of these compilers do this
    #define BOOST_SERIALIZATION_SHARED_PTR(T)                         \
    BOOST_CLASS_VERSION(                                              \
        ::std::shared_ptr< T >,                                     \
        1                                                             \
    )                                                                 \
    BOOST_CLASS_TRACKING(                                             \
        ::std::shared_ptr< T >,                                     \
        ::boost::serialization::track_never                           \
    )                                                                 \
    /**/
#endif

namespace boost {
namespace serialization{

#ifndef BOOST_SERIALIZATION_SHARED_PTR_HPP
struct null_deleter {
    void operator()(void const *) const {}
};
#endif

/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// serialization for shared_ptr

template<class Archive, class T>
inline void save(
    Archive & ar,
    const std::shared_ptr< T > &t,
    const unsigned int /* file_version */
){
    // The most common cause of trapping here would be serializing
    // something like shared_ptr<int>.  This occurs because int
    // is never tracked by default.  Wrap int in a trackable type
    BOOST_STATIC_ASSERT((tracking_level< T >::value != track_never));
    const T * t_ptr = t.get();
    ar << boost::serialization::make_nvp("px", t_ptr);
}

template<class Archive, class T>
inline void load(
    Archive & ar,
    std::shared_ptr< T > &t,
    const unsigned int /*file_version*/
){
    // The most common cause of trapping here would be serializing
    // something like shared_ptr<int>.  This occurs because int
    // is never tracked by default.  Wrap int in a trackable type
    BOOST_STATIC_ASSERT((tracking_level< T >::value != track_never));
    T* r;
    ar >> boost::serialization::make_nvp("px", r);
    ar.reset(t,r);
}

template<class Archive, class T>
inline void serialize(
    Archive & ar,
    std::shared_ptr< T > &t,
    const unsigned int file_version
){
    // correct shared_ptr serialization depends upon object tracking
    // being used.
    BOOST_STATIC_ASSERT(
        boost::serialization::tracking_level< T >::value
        != boost::serialization::track_never
    );
    boost::serialization::split_free(ar, t, file_version);
}

} // namespace serialization
} // namespace boost

#endif // BOOST_SERIALIZATION_STD_SHARED_PTR_HPP

आप अंतर को <boost/serialization/shared_ptr.hpp> here

मूल रूप से,

  • नाम बदलकर गार्ड शामिल हैं
  • बदल गया boost::shared_ptr से std::shared_ptr
  • <boost/shared_ptr.hpp> बजाय <memory> शामिल है
  • अगर आप boost::shared_ptr का भी उपयोग करते हैं तो redefinition से null_deleter संरक्षित
  • हटाया गया BOOST_SERIALIZATION_SHARED_PTR_132_HPP - जो कुछ भी है?

अब तक, ऐसा लगता है कि यह ठीक काम कर रहा है।


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

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


अरे दोस्तों ने आखिरकार बूस्ट सीरियलाइजेशन का उपयोग करके 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;

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


बूस्ट 1.56 के रूप में, serialization लाइब्रेरी में std :: shared_ptr के लिए अंतर्निहित समर्थन है । यदि आप लाइब्रेरी के एक नवीनतम संस्करण का उपयोग कर सकते हैं तो आपको अपने स्वयं के क्रमबद्ध सहायक कार्यों को लागू करने की आवश्यकता नहीं है।







boost-serialization