2012-09-09 16 views
27

के साथ कस्टम डिलीटर का उपयोग करके मैं एक कस्टम डिलीटर के साथ std :: shared_ptr का उपयोग करने का तरीका जानने का प्रयास कर रहा हूं। विशेष रूप से, मैं इसका उपयोग एसडीएल_Surface के साथ कर रहा हूं:std :: shared_ptr

std::shared_ptr<SDL_Surface>(SDL_LoadBMP(....),SDL_FreeSurface); 

जो संकलित करता है और ठीक चलाता है। हालांकि, मैं अपना खुद का हटाना चाहता हूं और ऐसा नहीं कर सकता कि ऐसा कैसे किया जाए। SDL_FreeSurface के लिए प्रलेखन यहाँ पाया जाता है:

http://sdl.beuc.net/sdl.wiki/SDL_FreeSurface

जिसमें मैं SDL_FreeSurface खोजने के रूप में घोषित किया जाता है:

void SDL_FreeSurface(SDL_Surface* surface); 

एक परीक्षण के रूप में, और उस जानकारी को देखते हुए, मैंने कोशिश की निम्नलिखित समारोह:

void DeleteSurface(SDL_Surface* surface) 
{ 
    std::cout << "Deleting surface\n"; 
    SDL_FreeSurface(surface); 
} 

हालांकि, जी के साथ ++ संकलन मुझे निम्न त्रुटि देता है:

error: no matching function for call to 'std::shared_ptr<SDL_Surface>::shared_ptr(SDL_Surface*, <unresolved overloaded function type>)' 

मैंने gcc std :: shared_ptr कार्यान्वयन के लिए gnu दस्तावेज़ को देखा है लेकिन इसका अधिक अर्थ नहीं उठा सकता है। मैं क्या गलत कर रहा हूं?

संपादित करें: मैंने तब से समस्या को कम कर दिया है, लेकिन ऊपर मूल प्रश्न छोड़ देगा। जैसा कि ऊपर DeleteSurface के कार्यान्वयन के साथ

class Game { 
    public: 
     /* various functions */ 
    private: 
     void DeleteSurface(SDL_Surface* surface); 
     bool CacheImages(); 
     std::vector<std::shared_ptr<SDL_Surface> > mCachedImages; 

     /* various member variables and other functions */ 
} 

, और जैसा कि CacheImages() के कार्यान्वयन:

bool CacheImages() 
{ 
    mCachedImages.push_back(std::shared_ptr<SDL_Surface>(SDL_LoadBMP(...),DeleteSurface); 
    return true; 
} 
क्या मैं था एक खेल वर्ग है, जो अगर मैं इसे एक बुनियादी कार्यान्वयन के लिए नीचे पट्टी, की तरह कुछ था

जो मुझे ऊपर सूचीबद्ध त्रुटि खेल है। हालांकि, अगर मैं DeleteSurface()Game कक्षा के बाहर फ़ंक्शन को अन्यथा बदलने के बिना स्थानांतरित करता हूं, तो कोड संकलित करता है। DeleteSurface फ़ंक्शन Game क्लास में समस्याएं पैदा करने वाले बारे में क्या है?

+0

आपका उदाहरण मेरे लिए ठीक संकलित करता है। –

उत्तर

42
std::shared_ptr<SDL_Surface>(SDL_LoadBMP(....), [=](SDL_Surface* surface) 
{ 
    std::cout << "Deleting surface\n"; 
    SDL_FreeSurface(surface); 
}); 

या

void DeleteSurface(SDL_Surface* surface) 
{ 
    std::cout << "Deleting surface\n"; 
    SDL_FreeSurface(surface); 
} 

std::shared_ptr<SDL_Surface>(SDL_LoadBMP(....), DeleteSurface); 

संपादित करें:

अपने अपडेट किए गए सवाल को देखकर, DeleteSurface एक गैर सदस्य समारोह होना चाहिए, अन्यथा आप std::bind या std::mem_fn या कुछ अन्य सदस्य समारोह सूचक एडाप्टर का उपयोग करने की आवश्यकता है ।

+0

आपका दूसरा उदाहरण वह है जो मेरे पास पहले से था, जो संकलित नहीं होगा। – Wheels2050

+0

@ व्हील 2050: यह ठीक से संकलित करता है, आप उस मामले में अपने उदाहरण से कुछ छोड़ रहे हैं। – ronag

+0

क्षमा करें, आप सही हैं - मैंने अपना प्रश्न संपादित कर लिया है। – Wheels2050

8

यह कोड एक ऑब्जेक्ट विधि के रूप में हटाए गए साझा सूचक के साथ एक साझा सूचक निर्माण का एक उदाहरण प्रदान करता है। यह उपयोग करने के लिए std::bind निर्देश प्रदर्शित करता है।

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

recyler आसानी से get() और add() तरीकों के लिए एक महत्वपूर्ण जोड़कर और एक std::map में वस्तुओं के भंडारण के द्वारा एक वस्तु कैश में बदला जा सकता।

class ObjRecycler 
{ 
private: 
    std::vector<Obj*> freeObjPool; 
public: 
    ~ObjRecycler() 
    { 
     for (auto o: freeObjPool) 
      delete o; 
    } 

    void add(Obj *o) 
    { 
     if (o) 
      freeObjPool.push_back(o); 
    } 

    std::shared_ptr<Obj> get() 
    { 
     Obj* o; 
     if (freeObjPool.empty()) 
      o = new Obj(); 
     else 
     { 
      o = freeObjPool.back(); 
      freeObjPool.pop_back(); 
     } 
     return std::shared_ptr<Obj>(o, 
      std::bind(&ObjRecycler::add, this, std::placeholders::_1)); 
    } 
} 
+1

बस कहना चाहता था कि यह इरादे से काम नहीं करता है। जब आप 'get() 'को कॉल करते हैं, तो आप ** हमेशा **' 1' की संदर्भ संख्या के साथ एक साझा सूचक प्राप्त करेंगे। इससे भी बदतर, कई साझा पॉइंटर्स फिर उसी स्मृति को इंगित कर सकते हैं। यदि कोई गुंजाइश से बाहर हो जाता है, तो आपको segfaults मिल जाएगा। आपको जो चाहिए वह 'std :: वेक्टर ' नहीं है, लेकिन एक 'std :: vector >'। – rwols

+0

आप 'std :: vector >' नहीं चाहते हैं क्योंकि यह उस बफर के जीवनकाल को सुरक्षित नहीं रखेगा जिसे आप पुन: उपयोग करना चाहते हैं, आप एक 'std :: vector चाहते हैं > इसके बजाए। आप अपने पूर्व-मौजूदा 'std :: unique_ptr' से एक 'std :: shared_ptr' बना सकते हैं और फिर कस्टम डिलीटर कच्चे अब-अप्रमाणित सूचक को ले जा सकते हैं और इसे एक नए' std :: unique_ptr' में डाल सकते हैं और डाल सकते हैं कि आपके 'std :: वेक्टर' में। –

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