2009-07-10 25 views
25

की क्षमता को कम करें क्या वेक्टर की क्षमता को कम करने का कोई तरीका है?एक एसएलएल वेक्टर

मेरा कोड वेक्टर में मूल्यों को आवंटित करता है (पहले से उनके नंबर को नहीं जानता), और जब यह खत्म होता है, तो वेक्टर केवल पढ़ने के लिए उपयोग किए जाते हैं।

मुझे लगता है कि मैं एक नया वेक्टर बना सकता हूं, आकार के साथ एक .reseve() कर सकता हूं और आइटम कॉपी करता हूं, लेकिन मुझे वास्तव में अतिरिक्त प्रतिलिपि ऑपरेशन पसंद नहीं है।

पीएस: मुझे पोर्टेबल समाधान की परवाह नहीं है, जब तक यह जीसीसी के लिए काम करता है।

+4

बस एक नोट, रिजर्व() जरूरी सटीक राशि आप इसे पारित आरक्षित नहीं करता है; यह आपके द्वारा आरक्षित राशि() के बराबर राशि के बराबर या बराबर राशि सुरक्षित रखता है। – DeadHead

+1

ध्यान दें कि स्वैप मुहावरा एक प्रतिलिपि करता है। मुझे नहीं पता कि जीसीसी के पास अप्रयुक्त आरक्षित मेमोरी जारी करने का विस्तार है या नहीं। मेरी राय में ऐसी विधि वेक्टर <> के लिए मानक में होनी चाहिए। –

+4

वेक्टर के बजाय डेक का उपयोग करने पर विचार करें। यह लगभग वेक्टर के रूप में तेज़ है लेकिन डेटा को संक्रामक ब्लॉक में नहीं रखता है और इसे आरक्षित की आवश्यकता नहीं है() – Wacek

उत्तर

37
std::vector<T>(v).swap(v); 

सामग्री गमागमन एक और वेक्टर के साथ क्षमता स्वैप देखें।

std::vector<T>(v).swap(v); ==> is equivalent to 

std::vector<T> tmp(v); // copy elements into a temporary vector 
     v.swap(tmp);    // swap internal vector data 

स्वैप() केवल आंतरिक डेटा संरचना को बदल देगा। स्कॉट Meyers प्रभावी एसटीएल आइटम 17.

पर

+2

हां - यह अनिवार्य रूप से एक प्रति है। AFAIK ओपी चाहता है कि यह करने का एकमात्र मानक तरीका है। जहां तक ​​गैर-मानक तरीका है जो प्रतिलिपि से बचाता है (जिसे ओपी स्वीकार्य लगेगा), मुझे यकीन नहीं है कि जीसीसी के एसटीएल में यह है (लेकिन अगर यह करता है तो मुझे आश्चर्य नहीं होगा)। –

+0

माइकल, मुझे संदेह है कि यह काम करने के लिए मानक द्वारा गारंटीकृत है। – avakar

+3

@avakar - हाँ यह मानक द्वारा काम करने की गारंटी है (क्या हो रहा है के एजे के टूटने को देखें)। लेकिन यह मूल वेक्टर के सभी तत्वों की प्रतिलिपि बनाने की भी गारंटी है। –

6

मूर्खतापूर्ण समाधान नव निर्मित वेक्टर के साथ स्वैप करना है।

vector<int>().swap(v); 

संपादित करें: मैं सवाल पढ़ने में भूलना। उपरोक्त कोड वेक्टर को साफ़ करेगा। ओपी तत्वों को छूटे रखना चाहता है, केवल capacity() से size() को छोटा करें।

यह कहना मुश्किल है कि एजे का कोड ऐसा करेगा या नहीं। मुझे संदेह है कि पोर्टेबल समाधान है। gcc के लिए, आपको vector के उनके विशेष कार्यान्वयन पर एक नज़र डालना होगा।

संपादित करें: इसलिए मैंने libstdC++ कार्यान्वयन पर देखा है। ऐसा लगता है कि एजे का समाधान वास्तव में काम करेगा।

vector<int>(v).swap(v); 

the source, लाइन 232.

+1

नोट - यह वेक्टर के लिए स्मृति जारी करता है - लेकिन यह * सभी * तत्वों को भी हटा देता है (क्योंकि आप एक खाली अस्थायी वेक्टर के साथ स्वैप कर रहे हैं)। –

13

जाओ देखो मूल रूप से आप सीधे एक std :: वेक्टर के भंडारण के आकार को कम नहीं कर सकते। आकार बदलें और शोध कभी भी एक कंटेनर की वास्तव में स्मृति पदचिह्न को कम नहीं करेगा। "चाल" सही आकार का एक नया कंटेनर बनाना है, डेटा कॉपी करें और वर्तमान कंटेनर के साथ स्वैप करें। हम एक कंटेनर खाली करने के लिए चाहते हैं, तो बाहर यह बस है:

std::vector<T>().swap(v); 

हम तो पर डेटा हम नकल करने की जरूरत है कॉपी करने के लिए है, तो:

std::vector<T>(v).swap(v); 

क्या करता है एक नया बनाता है पुराने से डेटा के साथ वेक्टर, उस प्रतिलिपि को कॉपी करना जो किसी भी ऑपरेशन में आवश्यक होगा जिसके प्रभाव की आपको आवश्यकता है। फिर स्वैप कॉल करना ऑब्जेक्ट्स के बीच आंतरिक बफर को स्वैप करेगा। लाइन के अंत में बनाया गया अस्थायी वेक्टर हटा दिया गया है, लेकिन पुराने पुराने वेक्टर से गड़बड़ है और पुराने वेक्टर की नई प्रतिलिपि है जो हमें आवश्यक सटीक आकार है।

2

मैं यह नहीं कह रहा हूं कि जीसीसी के पास एक प्रतिलिपि के बिना जो कुछ भी आप चाहते हैं उसे करने के लिए कुछ तरीका नहीं हो सकता है, लेकिन यह लागू करना मुश्किल होगा (मुझे लगता है) क्योंकि वैक्टर को Allocator ऑब्जेक्ट को आवंटित करने और स्मृति को आवंटित करने की आवश्यकता है , और Allocator के लिए इंटरफ़ेस में reallocate() विधि शामिल नहीं है।मुझे नहीं लगता कि यह करना असंभव होगा, लेकिन यह मुश्किल हो सकता है।

+0

मुझे लगता है कि वेक्टर कंटेनर के लिए असंभव होगा, क्योंकि तत्वों को स्मृति में विरोधाभासी होना आवश्यक है। मुझे एहसास हुआ कि नहीं कि allocators केवल .allocate() और .deallocate() थी, इसलिए मुझे लगता है कि यही कारण है कि ऐसी कार्यक्षमता मौजूद नहीं है। – ynimous

+1

realloc() फ़ंक्शन सी में आसान है, लेकिन जब आप स्मृति आवंटन में अधिक अर्थशास्त्र जोड़ना शुरू करते हैं तो यह अधिक जटिल हो जाता है। मुझे लगता है कि यही कारण है कि सी ++ में कोई समकक्ष नहीं है। –

3

नहीं, आप प्रतिलिपि के बिना वेक्टर की क्षमता को कम नहीं कर सकते हैं। हालांकि, आप नियंत्रित करते समय क्षमता() और कॉल रिजर्व() को चेक करके कितनी नई आवंटन वृद्धि को नियंत्रित कर सकते हैं। Std :: वेक्टर के लिए डिफ़ॉल्ट व्यवहार नई क्षमता की आवश्यकता होने पर हर बार 2 के कारक द्वारा अपनी क्षमता बढ़ाना है। आप अपनी खुद की जादू अनुपात से यह वृद्धि कर सकते हैं:

template <typename T> 
void myPushBack(std::vector<T>& vec, const T& val) { 
    if (vac.size() + 1 == vac.capacity()) { 
     vac.reserve(vac.size() * my_magic_ratio); 
    } 

    vec.push_back(val); 
} 

आप थोड़ा hacky तकनीक में कर रहे हैं, तो आप हमेशा अपनी खुद की संभाजक में गुजरती हैं और जो कुछ भी आप अप्रयुक्त क्षमता को पुनः प्राप्त करने करने की जरूरत कर सकते हैं।

31

सी ++ 11 के साथ, आप सदस्य फ़ंक्शन shrink_to_fit() पर कॉल कर सकते हैं। draft standard खंड 23.2.6.2 का कहना है:

shrink_to_fit एक गैर बाध्यकारी अनुरोध size() को capacity() कम करना है। [नोट: अनुरोध पर बाध्यकारी है कार्यान्वयन-विशिष्ट अनुकूलन के लिए अक्षांश की अनुमति दें। अंत टिप्पणी]

1

आप अपने वेक्टर की भूमि के ऊपर तो हो सकता है आप डेटा संरचना का एक और प्रकार का उपयोग कर के लिए देख जाना चाहिए के बारे में बारे में चिंतित हैं। आपने उल्लेख किया है कि एक बार आपका कोड वेक्टर शुरू करने के बाद किया जाता है, यह केवल पढ़ने की प्रक्रिया बन जाता है। मैं एक ओपन एंडेड सरणी के साथ जाने का सुझाव दूंगा जो कार्यक्रम को संकलित समय पर अपनी क्षमता का निर्धारण करने की अनुमति देगा। या शायद एक लिंक्ड सूची आपकी आवश्यकताओं के लिए अधिक उपयुक्त होगी।
लेमेम को पता है कि क्या मैं पूरी तरह से गलत समझ रहा हूं कि आप क्या प्राप्त कर रहे थे।

+0

यदि आपके पास केवल बहुत कम तत्व हैं तो अन्य डेटा संरचनाओं में अधिक ओवरहेड होता है। यदि ऐसा कोई मामला है जहां मुझे लाखों कंटेनरों की आवश्यकता है। std :: वेक्टर को इस मामले में काफी कम स्मृति की आवश्यकता है। –

0

स्कॉट मायर्स द्वारा "प्रभावी एसटीएल" पुस्तक प्राप्त -UBcse। वेक्टर की क्षमता को कम करने पर एक पूर्ण वस्तु जुस है।

1

पुराना धागा, मुझे पता है, लेकिन अगर कोई भविष्य में इसे देख रहा है .. सी ++ 11 में shrink_to_fit() है लेकिन चूंकि यह एक बाध्यकारी अनुरोध है, तो व्यवहार इसके कार्यान्वयन पर निर्भर करेगा।

देखें: http://en.cppreference.com/w/cpp/container/vector/shrink_to_fit

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