2013-03-08 5 views
8

मुझे पता है कि मैन्युअल गतिशील स्मृति आवंटन सामान्य रूप से एक बुरा विचार है, लेकिन क्या यह कभी-कभी std::vector का उपयोग करने से बेहतर समाधान है?std :: वेक्टर का उपयोग करने के लिए ओवरहेड?

एक क्रूड उदाहरण देने के लिए, अगर मुझे n पूर्णांक की एक सरणी स्टोर करना पड़ा, जहां n < = 16 कहें।

std::vector<int> data; 

यह बिल्कुल हमेशा एक बेहतर विचार एक std::vector उपयोग करने के लिए या व्यावहारिक स्थितियों में, जहां मैन्युअल गतिशील स्मृति आवंटन एक होगा हो सकता है: मैं

int* data = new int[n]; //assuming n is set beforehand 

का उपयोग कर या एक सदिश का उपयोग कर इसे लागू कर सकता है दक्षता बढ़ाने के लिए बेहतर विचार?

+0

आपको 'push_back' । 'std :: vector (n)' है * लगभग * आपके गतिशील सरणी संस्करण के बराबर है, सिवाय इसके कि 'n' पूर्णांक मान हैं, इसलिए शून्य, वेक्टर में प्रारंभ किया गया है। – juanchopanza

+0

@juanchopanza: उचित बिंदु। मैंने 'push_back' भाग हटा दिया। यह तुलना का हिस्सा नहीं माना जाता था। –

उत्तर

11

यह हमेशा std::vector/std::array उपयोग करने के लिए, कम से कम जब तक आप अंतिम तौर साबित कर सकते हैं (रूपरेखा के माध्यम से) कि T* a = new T[100]; समाधान काफी तेज अपने विशिष्ट स्थिति में है बेहतर है। ऐसा होने की संभावना नहीं है: vector/array एक सादे पुराने सरणी के चारों ओर एक बेहद पतली परत है। vector::at के साथ जांच करने के लिए कुछ ओवरहेड है, लेकिन आप operator[] का उपयोग कर इसे बाधित कर सकते हैं।

+3

सी स्टाइल सरणी का उपयोग करने का सामान्य कारण गति से कुछ लेना देना नहीं है; यह स्थिर आरंभीकरण के लिए है, और संकलक के लिए initializers की संख्या के अनुसार आकार निर्धारित करने।(जो, ज़ाहिर है, कभी गतिशील आवंटित सरणी पर लागू नहीं होता है)। –

+0

@ जेम्स यदि मैं आपकी टिप्पणी सही तरीके से पढ़ रहा हूं, तो आप इस तथ्य पर आक्षेप कर रहे हैं कि मैं सी-स्टाइल सरणी को बिना किसी कहने के बाध्य कर रहा हूं कि मेरा मतलब गतिशील रूप से आवंटित है? यदि हां, तो मैंने इसके बारे में अपना जवाब संपादित कर लिया है। (इसके अलावा, आपके उत्तर में +1।) – us2012

+1

यह इसे साफ़ करता है। मुझे नहीं पता था कि 'वेक्टर'/'सरणी 'एक पतली परत है। मुझे लगता है कि सभी कार्यक्षमताओं के साथ, यह एक महत्वपूर्ण ओवरहेड होना चाहिए। –

4

यदि आप पहले से आकार (विशेष रूप से संकलन समय पर) जानते हैं, और std::vector की गतिशील पुन: आकार की क्षमताओं की आवश्यकता नहीं है, तो कुछ आसान उपयोग करना ठीक है।

हालांकि, अगर आपके पास C++ 11 है, या boost::scoped_array जैसे कुछ अन्यथा होना चाहिए तो अन्यथा std::array होना चाहिए।

मुझे संदेह है कि इसमें बहुत अधिक दक्षता लाभ होगा जब तक कि यह कोड आकार या कुछ कम कर देता है, लेकिन यह अधिक अभिव्यक्तिपूर्ण है जो वैसे भी सार्थक है।

4

आपको जब भी संभव हो C++ में C-स्टाइल-एरे से बचने का प्रयास करना चाहिए। STL कंटेनर प्रदान करता है जो आमतौर पर हर आवश्यकता के लिए पर्याप्त होता है। बस एक सरणी के लिए पुनर्वितरण की कल्पना करें या इसके मध्य से बाहर तत्वों को हटा दें। कंटेनर आपको इसे संभालने से बचाता है, जबकि आपको इसे अपने लिए ख्याल रखना होगा, और यदि आपने यह सौ बार नहीं किया है तो यह काफी त्रुटि-प्रवण है।
एक अपवाद निश्चित रूप से है, यदि आप निम्न स्तर के मुद्दों को संबोधित कर रहे हैं जो STL -containers से निपटने में सक्षम नहीं हो सकते हैं।

इस विषय के बारे में कुछ चर्चा पहले ही हो चुकी है। SO पर here देखें।

+0

+1, जो एक बार और सभी मिथकों के लिए नष्ट हो जाना चाहिए जो वेक्टर तत्वों तक पहुंचने से धीमा हो। लिंक के लिए – us2012

+0

+1। मुझे पहले यह पता होना चाहिए था कि वास्तव में ... –

0

n में संकलन समय पर जाना जाता है, तो आप std::array के रूप में चुनना चाहिए:

std::array<int, n> data; //n is compile-time constant 

और अगर n संकलन समय पर नहीं जाना जाता है, या सरणी क्रम से बढ़ने सकता है, तो std::vector के लिए जाना :

std::vector<int> data(n); //n may be known at runtime 

या कुछ मामलों में, आप भी std::deque जो कुछ परिदृश्य में std::vector तेजी से है पसंद कर सकते हैं।इन देखें:

आशा है कि मदद करता है के द्वारा।

+0

जब तक आप नहीं जानते कि 'n' बहुत छोटा है, तो आपको शायद स्थानीय चर को 'std :: array' के रूप में घोषित नहीं करना चाहिए। जब तक कि अन्यथा करने के लिए कुछ बहुत ही विशिष्ट कारण नहीं है, मैं केवल 'std :: vector' का उपयोग करता हूं --- यदि मुझे आकार पता है, तो मैं वेक्टर को सही आकार के साथ प्रारंभ करूंगा। (यह भी मानता है कि इस प्रकार का डिफॉल्ट कन्स्ट्रक्टर है।) –

3

यह बिल्कुल हमेशा एक बेहतर विचार एक std :: वेक्टर उपयोग करने के लिए या व्यावहारिक स्थितियों में, जहां मैन्युअल गतिशील स्मृति आवंटन एक बेहतर विचार होगा, क्षमता बढ़ाने के लिए हो सकता है है?

मुझे एक साधारण बटन कहें, लेकिन 99.9 999 ... बार बार मैं मानक कंटेनर का उपयोग करता हूं। डिफ़ॉल्ट विकल्प std::vector होना चाहिए, लेकिन std::deque<> could be a reasonable option sometimes भी होना चाहिए। यदि आकार संकलन-समय पर जाना जाता है, तो std::array<> का चयन करें, जो सी-स्टाइल सरणी का हल्का, सुरक्षित आवरण है जो शून्य ओवरहेड पेश करता है।

मानक कंटेनर प्रारंभिक आरक्षित राशि निर्दिष्ट करने के लिए सदस्य कार्यों का पर्दाफाश करते हैं, इसलिए आपको पुनर्विक्रय के साथ परेशानी नहीं होगी, और आपको delete[] को अपने सरणी में याद रखना होगा। मैं ईमानदारी से नहीं देखता कि क्यों मैनुअल मेमोरी प्रबंधन का उपयोग करना चाहिए।

क्षमता एक मुद्दा नहीं होना चाहिए, जब से तुम फेंक दिया है और निहित तत्वों का उपयोग करने के लिए गैर फेंकने सदस्य काम करता है, तो आप सुरक्षा या प्रदर्शन के पक्ष में है कि क्या एक विकल्प नहीं है।

2

std :: वेक्टर एक size_type पैरामीटर है कि तत्वों की निर्दिष्ट संख्या के साथ वेक्टर का दृष्टांत के साथ निर्माण किया जा सकता है और कहा कि (अपने सरणी के रूप में ही) एक एकल गतिशील आवंटन करता है और यह भी आप कम करने के लिए आरक्षित उपयोग कर सकते हैं उपयोग समय पर पुनः आवंटन की संख्या।

8

मैं किसी भी मामले में जहां गतिशील रूप से एक सी शैली वेक्टर समझ में आता है के आवंटन के बारे में सोच नहीं कर सकते।

std::vector<int> data(n); 

रहे हैं: (। मैं 25 साल के लिए C++ काम कर रहा है, और मैं अभी तक new[] उपयोग करने के लिए है) आम तौर पर, अगर मैं सामने आकार पता है, मैं की तरह कुछ का उपयोग करेंगे push_back का उपयोग करने के बजाय, पहले से ही आकार का वेक्टर प्राप्त करें।

बेशक

, अगर n बहुत छोटा है और संकलन समय पर जाना जाता है, मैं std::array इस्तेमाल करेंगे (अगर मैं करने के लिए सी ++ 11 उपयोग किया है), या यहाँ तक एक सी शैली सरणी, और सिर्फ वस्तु बनाने स्टैक पर, कोई गतिशील आवंटन के साथ। (ऐसे मामले कोड में दुर्लभ प्रतीत होते हैं; छोटे फिक्स्ड साइज एरे कक्षाओं के सदस्य होते हैं। जहां मैं कभी-कभी सी स्टाइल सरणी का उपयोग करता हूं।)

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