मैं एक मौजूदा ऐप को अपग्रेड करने के लिए स्मार्ट पॉइंटर्स का उपयोग करने का प्रयास कर रहा हूं, और मैं एक पहेली को दूर करने की कोशिश कर रहा हूं। मेरे ऐप में मेरे पास ऑब्जेक्ट्स का कैश है, उदाहरण के लिए उन्हें किताबें कॉल करें। अब आईडी द्वारा किताबों के इस कैश का अनुरोध किया जाता है और यदि वे कैश में हैं तो वे वापस आ जाते हैं, अगर ऑब्जेक्ट को बाहरी सिस्टम (धीमी ऑपरेशन) से अनुरोध नहीं किया जाता है और कैश में जोड़ा जाता है। एक बार कैश में ऐप में कई खिड़कियां खोली जा सकती हैं, इनमें से प्रत्येक विंडो पुस्तक का संदर्भ ले सकती है। ऐप के पिछले संस्करण में प्रोग्रामर को एड्रफ और रिलीज को बनाए रखना था, जब पुस्तक ऑब्जेक्ट का उपयोग करने वाली प्रत्येक विंडो बंद थी, अंतिम रिलीज (कैश मैनेजर पर) ऑब्जेक्ट को कैश से निकाल देगा और ऑब्जेक्ट को हटा देगा।कोई संदर्भ नहीं होने पर कैश से स्मार्ट पॉइंटर्स को कैसे निकालें?
आपने यहां श्रृंखला में कमजोर लिंक देखा होगा, यह निश्चित रूप से प्रोग्रामर को एड्रफ और रिलीज को कॉल करना याद रखता है। अब मैं स्मार्ट पॉइंटर्स (बूस्ट :: घुसपैठ) में स्थानांतरित हो गया हूं, अब मुझे एड्रफ और रिलीज को कॉल करने के बारे में चिंता करने की ज़रूरत नहीं है। हालांकि इससे किसी समस्या का कारण बनता है, कैश में ऑब्जेक्ट का संदर्भ होता है, इसलिए जब अंतिम विंडो बंद होती है, तो कैश को अधिसूचित नहीं किया जाता है कि कोई भी संदर्भ नहीं रख रहा है।
मेरा पहला विचार समय-समय पर कैश और पुर्ज ऑब्जेक्ट्स को संदर्भ संदर्भ के साथ चलाना था। मुझे यह विचार पसंद नहीं आया, क्योंकि यह एक ऑर्डर एन ऑपरेशन था और सही महसूस नहीं किया। मैं एक कॉलबैक सिस्टम के साथ आया हूं, जो बेहतर है लेकिन शानदार नहीं है। मैंने कॉलबैक सिस्टम के लिए कोड शामिल किया है, हालांकि मैं सोच रहा था कि क्या किसी को ऐसा करने का बेहतर तरीका है?
class IContainer
{
public:
virtual void FinalReference(BaseObject *in_obj)=0;
};
class BaseObject
{
unsigned int m_ref;
public:
IContainer *m_container;
BaseObject() : m_ref(0),m_container(0)
{
}
void AddRef()
{
++m_ref;
}
void Release()
{
// if we only have one reference left and we have a container
if(2 == m_ref && 0 != m_container)
{
m_container->FinalReference(this);
}
if(0 == (--m_ref))
{
delete this;
}
}
};
class Book : public BaseObject
{
char *m_name;
public:
Book()
{
m_name = new char[30];
sprintf_s(m_name,30,"%07d",rand());
}
~Book()
{
cout << "Deleting book : " << m_name;
delete [] m_name;
}
const char *Name()
{
return m_name;
}
};
class BookList : public IContainer
{
public:
set<BookIPtr> m_books;
void FinalReference(BaseObject *in_obj)
{
set<BookIPtr>::iterator it = m_books.find(BookIPtr((Book*)in_obj));
if(it != m_books.end())
{
in_obj->m_container = 0;
m_books.erase(it);
}
}
};
namespace boost
{
inline void intrusive_ptr_add_ref(BaseObject *p)
{
// increment reference count of object *p
p->AddRef();
}
inline void intrusive_ptr_release(BaseObject *p)
{
// decrement reference count, and delete object when reference count reaches 0
p->Release();
}
} // namespace boost
चीयर्स रिच
आपको 'बेसऑब्जेक्ट' को अनावश्यक बनाना चाहिए (घोषित करके, लेकिन एक निजी प्रतिलिपि कन्स्ट्रक्टर और असाइनमेंट ऑपरेटर परिभाषित नहीं करना चाहिए), या इसे किसी भी तरह से उचित रूप से कॉपी करने योग्य बनाना चाहिए। इसी तरह, 'बुक' में खतरनाक प्रति अर्थशास्त्र है, जो मैन्युअल रूप से प्रबंधित सरणी के बजाय 'std :: string' का उपयोग करके सबसे अच्छा तय किया जाता है। –
आभासी dtor कृपया !!! – curiousguy