2013-09-24 3 views
5

च 11 व्यायाम 11-6 पर मिटाने के फ़ंक्शन में फंस गया। मैंने ऑब्जेक्ट्स को नष्ट कर दिया है लेकिन मुझे नहीं पता कि अंतरिक्ष को वापस करने के लिए आवंटक लाइब्रेरी से डीलोकेशन का उपयोग कैसे किया जाए।त्वरित सी ++ व्यायाम 11-6

कृपया मुझे जमानत दें। पीएस: यह होमवर्क नहीं है लेकिन मैं घर पर अभ्यास कर रहा हूं

नीचे त्वरित सी ++ से कोड है और उसके बाद मेरा संशोधित मिटा कार्य। धन्यवाद `

template <class T> class Vec 
{ 
public: 
    typedef T* iterator; 
    typedef const T* const_iterator; 
    typedef size_t size_type; 
    typedef T value_type; 
    typedef T& reference; 
    typedef const T& const_reference; 

    Vec() { create(); } 
    explicit Vec(size_type n, const T& t = T()) { create(n, t); } 
    Vec(const Vec& v) { create(v.begin(), v.end()); } 
    Vec& operator=(const Vec&); 
    ~Vec() { uncreate(); } 

    T& operator[](size_type i) { return data[i]; } 
    const T& operator[](size_type i) const { return data[i]; } 

    void push_back(const T& t) 
    { 
     if (avail == limit) 
     { 
      grow(); 
     } 

     unchecked_append(t); 
    } 

    iterator erase(iterator); 
    iterator erase(iterator, iterator); 
    void clear(); 

    size_type size() const { return avail - data; } 

    iterator begin() { return data; } 
    const iterator begin() const { return data; } 

    iterator end() { return avail; } 
    const iterator end() const { return avail; } 

private: 
    iterator data; 
    iterator avail; 
    iterator limit; 

    std::allocator<T> alloc; 

    void create(); 
    void create(size_type, const T&); 
    void create(const_iterator, const_iterator); 

    void uncreate(); 

    void grow(); 
    void unchecked_append(const T&); 
}; 

मेरा कोड

template <class T> typename Vec<T>::iterator Vec<T>::erase(iterator first, iterator second) 
{ 
    if(second < first) 
    { 
     throw std::out_of_range("Iterator out of bounds."); 
    } 
    if(first < data || second >= avail) 
    { 
     throw std::out_of_range("Iterator out of bounds."); 
    } 
    iterator last = avail -1 ; 
    iterator i = first ; 
    iterator j = second ; 
    while(j <= last) 
    { 
     *i++ = *j++ ; 

    } 
    // destroy each initilsed space 
    iterator new_avail = avail - first + second ; 

    std::cout << " end " << end() << std::endl; 

    while(avail != new_avail) 
    { 
     alloc.destroy(--avail) ; 
    } 


    // dellocate space how to do that ? 
    alloc.deallocate(avail -1, ); // not sure what to do here 
    return first ; 

} 
+0

आप वास्तव में क्या करने की कोशिश कर रहे हैं? – thecoshman

उत्तर

4

आप आवंटित स्मृति के एक हिस्से को हटा नहीं सकते हैं।

alloc.deallocate (avail -1,);

कोई अच्छा नहीं है।

संपादित

आप मिटा में आवंटन mangage करने की कोशिश नहीं करनी चाहिए। आपके पास एक विकल्प है जो इसे पुन: आवंटित करना है, जिससे मिटाना और भी महंगा हो जाएगा। एक दूसरा कार्य कर सकता है:

iterator shrink(iterator first, iterator last) { 

    size_type capacity = (limit - data) - (last - first); 

    iterator new_data = alloc.allocate(capacity); 
    iterator new_avail = new_data; 
    iterator source = data; 
    while(source < first) 
     // C++11 
     alloc.construct(new_avail++, std::move(*source++)); 
    source = last; 
    iterator result = new_avail; 
    while(source < avail) 
     // C++11 
     alloc.construct(new_avail++, std::move(*source++)); 
    while(data < avail) 
     alloc.destroy(--avail); 
    data = new_data; 
    avail = new_avail; 
    limit = new_data + capacity; 

    return result; 
} 

एक बेहतर विकल्प यह मानक तरीका है। एक अतिरिक्त निर्माता, स्वैप और shrink_to_fit जोड़ें:

Vec(const_iterator first, const_iterator last) { 
    create(first, last); 
} 

void swap(Vec& other) { 
    std::swap(data, other.data); 
    ... 
} 

bool shrink_to_fit() { 
    try 
    { 
     Vec(begin(), end()).swap(*this); 
     return true; 
    } 
    catch(...) {} 
    return false; 
} 

अब आप वेक्टर पर एक से अधिक आपरेशन लागू करते हैं और अंत में स्मृति की खपत हटना कर सकते हैं।

v.erase(a, b); 
v.erase(c, d); 
... 
v.shrink_to_fit(); 
2

मुझे लगता है, समाधानों में से एक नीचे दिए गए आकार के साथ एक नया वेक्टर बनाने के लिए है कि:

new_size = old_size - number_of_elements_to_delete 

तो फिर तुम शुरू से ही वस्तुओं की नकल पहली मिटाने वाली वस्तु के लिए, अंतिम मिटाई वस्तु से अंत तक और फिर पुराने वेक्टर को छोड़ दें।

यह सबसे अच्छा समाधान नहीं है लेकिन मुझे लगता है कि सबसे सरल है।

+0

उत्तर के लिए धन्यवाद, मुझे लगता है कि मैं जो कर रहा हूं वह भी बुरा नहीं है, मैं सिर्फ यह नहीं जानता कि सदस्य फ़ंक्शन को आवंटक से कैसे हटाया जाए। इसलिए ज्यादातर मुझे उसमें मदद की ज़रूरत है। धन्यवाद – samprat

2

यहाँ एक reference page for std::allocator::deallocate कहने के लिए मिल गया है है:

void deallocate(pointer p, size_type n);

भंडारण सूचक p है, जो एक सूचक allocate() के पहले के एक कॉल के द्वारा प्राप्त किया जाना चाहिए द्वारा संदर्भित deallocates। n तर्क allocate() पर कॉल के दूसरे तर्क के बराबर होना चाहिए जो मूल रूप से p का उत्पादन करता था।

यानी, आप आवंटित किए गए संग्रहण का एक हिस्सा नहीं हटा सकते हैं, केवल संपूर्ण हिस्सा।

समाधान भंडारण कि erase करने के लिए कॉल द्वारा नि: शुल्क किया जाता है वापस नहीं होगा। बस अपने सदस्य इटरेटर को तदनुसार अपडेट करें ताकि आप इस स्टोरेज को बाद में कॉल के लिए create पर उपलब्ध करा सकें। यह मानक कंटेनर vector भी करता है।

यदि आप वास्तव में अतिरिक्त संग्रहण वापस करना चाहते हैं, तो एक छोटे अस्थायी खंड आवंटित करें, वहां मौजूद कंटेनर में मौजूद तत्वों की प्रतिलिपि बनाएँ, पुराना संग्रहण जारी करें और इसे अद्यतन करें।

यहां ध्यान देने की बात अपवाद सुरक्षा है। एक बार जब आप एक अस्थायी बफर आवंटित कर लेते हैं, तो आपको यह सुनिश्चित करना होगा कि तत्वों की प्रतिलिपि बनाने के दौरान अपवाद होने पर आप इसे रिसाव न करें।

2

जैसा कि ज्रोक और अन्य ने उल्लेख किया है, आप स्मृति के हिस्से को अस्वीकार नहीं कर सकते - आपको entire referenced storage को हटाना होगा।

एक और महत्वपूर्ण बात है - अगर आप अध्याय 11 के माध्यम से देखने के लिए (विशेष रूप से, 11.4 के तहत, गतिशील Vecs), तो आप देखेंगे push_back() के लिए कार्यान्वयन अंतर्निहित सरणी के आकार दोगुना हो जाता है कि एक बार यह वर्तमान अधिकतम तक पहुँच जाता है आकार।

समान लाइनों पर, आप Halve अंतर्निहित सरणी के आकार जब अपने वेक्टर का आकार वर्तमान में अधिकतम आकार की एक चौथाई हो जाता है करना चाहते हैं। यह तब होता है जब आपको अतिरिक्त संग्रहण को रिलीज़ करने के लिए स्मृति को पुन: आवंटित करने और std::allocator::deallocate पर कॉल करने की आवश्यकता होती है।

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