QVector बनाम QList


80

मेरे पास पूर्णांकों की एक सूची है जो मुझे अधिक से अधिक पुनरावृत्त करने की आवश्यकता है लेकिन एक सरणी अपर्याप्त है। क्या अंतर हैं vectorsऔर listsऔर वहाँ कुछ भी मैं पता करने की जरूरत है इससे पहले कि मैं एक प्रकार चुनना होगा?

बस स्पष्ट होने के लिए, मैंने क्यूटी डॉक्स पढ़ा है लेकिन यह वही है जो मैं जानता हूं:

QList<T>, QLinkedList<T>और QVector<T>समान कार्यक्षमता प्रदान करते हैं। यहाँ एक अवलोकन है:

  • अधिकांश उद्देश्यों के लिए, QListउपयोग करने के लिए सही वर्ग है। इसका इंडेक्स-आधारित एपीआई QLinkedList'sइट्रेटर-आधारित एपीआई की तुलना में अधिक सुविधाजनक है , और यह आमतौर पर QVectorमेमोरी में अपने आइटम को स्टोर करने के तरीके की तुलना में अधिक तेज है । यह आपके निष्पादन योग्य में कम कोड तक भी फैलता है।
  • यदि आपको वास्तविक लिंक की गई सूची की आवश्यकता है, तो सूची के बीच में निरंतर समय सम्मिलन की गारंटी के साथ और आइटम्स को अनुक्रमित करने के बजाय आइटम का उपयोग करें QLinkedList
  • यदि आप चाहते हैं कि आइटम आसन्न मेमोरी पोजीशन पर कब्जा कर लें, तो उपयोग करें QVector

जवाबों:


122

QVectorजैसा std::vectorकि आप नाम से अनुमान लगा सकते हैं, ज्यादातर अनुरूप है । के साथ स्पष्ट सहयोग के बावजूद, QListकरीब है । यह वस्तुओं को सीधे स्टोर नहीं करता है, बल्कि उन्हें पॉइंटर्स को स्टोर करता है। आप दोनों सिरों पर त्वरित सम्मिलन के सभी लाभ प्राप्त करें और reallocations प्रतिलिपि कंस्ट्रक्टर्स के बजाय संकेत दिए गए फेरबदल को शामिल है, लेकिन एक वास्तविक की spacial इलाके खोना या , और ढेर आवंटन का एक बहुत प्राप्त करें। यह छोटी वस्तुओं के लिए ढेर के आवंटन से बचने के लिए कुछ निर्णय ले रहा है, जो स्थानिक इलाके को फिर से प्राप्त कर रहा है, लेकिन जो मैं समझता हूं कि यह केवल एक से छोटी चीजों पर लागू होता है ।boost::ptr_dequestd::liststd::dequestd::vectorint

QLinkedListके अनुरूप है std::list, और इसके सभी डाउनसाइड हैं। सामान्यतया, यह आपके कंटेनर का अंतिम विकल्प होना चाहिए।

क्यूटी लाइब्रेरी QListवस्तुओं के उपयोग के लिए बहुत अनुकूल है , इसलिए अपने स्वयं के कोड में उनका पक्ष लेना कभी-कभी कुछ अस्वाभाविक टेडियम से बच सकता है। अतिरिक्त हीप का उपयोग और वास्तविक डेटा की यादृच्छिक स्थिति कुछ परिस्थितियों में सैद्धांतिक रूप से चोट पहुंचा सकती है, लेकिन बार-बार अप्रभावी है। इसलिए मैं सुझाव देता हूं कि QListजब तक प्रोफाइलिंग एक को बदलने का सुझाव न दे QVector। यदि आप सन्निहित आवंटन को महत्वपूर्ण होने की उम्मीद करते हैं [पढ़ें: आप कोड के साथ हस्तक्षेप कर रहे हैं जो T[]एक QList<T>] के बजाय उम्मीद करता है कि यह भी QVectorबल्ले से सही से शुरू करने का एक कारण हो सकता है ।


यदि आप सामान्य रूप से कंटेनरों के बारे में पूछ रहे हैं, और केवल संदर्भ के रूप में क्यूटी दस्तावेजों का उपयोग किया है, तो उपरोक्त जानकारी कम उपयोगी है।

एक std::vectorसरणी है जिसे आप आकार बदल सकते हैं। सभी तत्व एक-दूसरे के बगल में संग्रहीत होते हैं, और आप व्यक्तिगत तत्वों को जल्दी से एक्सेस कर सकते हैं। नकारात्मक पक्ष यह है कि सम्मिलन केवल एक छोर पर कुशल होते हैं। यदि आप बीच में या शुरुआत में कुछ डालते हैं, तो आपको कमरे बनाने के लिए अन्य वस्तुओं को कॉपी करना होगा। बड़े-ओह संकेतन में, अंत में सम्मिलन O (1) है, कहीं भी सम्मिलन O (N) है, और यादृच्छिक अभिगम O (1) है।

एक std::dequeसमान है, लेकिन ग्वारेंटी वस्तुओं को एक दूसरे के बगल में संग्रहीत नहीं किया जाता है, और दोनों छोरों पर सम्मिलन की अनुमति देता है ओ (1)। इसे एक बार में आवंटित की जाने वाली मेमोरी के छोटे हिस्से की भी आवश्यकता होती है, जो कभी-कभी महत्वपूर्ण हो सकती है। रैंडम एक्सेस O (1) है और मध्य में सम्मिलन O (N) है, उसी तरह a के लिए vector। स्थानिक इलाके की तुलना में बदतर है std::vector, लेकिन वस्तुओं का क्लस्टर होना है तो आप कुछ लाभ प्राप्त करते हैं।

एक std::listलिंक की गई सूची है। इसके लिए तीन मानक अनुक्रमिक कंटेनरों में से सबसे अधिक मेमोरी ओवरहेड की आवश्यकता होती है, लेकिन कहीं भी तेजी से प्रविष्टि प्रदान करता है ... बशर्ते आप पहले से जानते हों कि आपको कहां सम्मिलित करना है। यह व्यक्तिगत तत्वों तक यादृच्छिक पहुँच प्रदान नहीं करता है, इसलिए आपको O (N) में पुनरावृत्त करना होगा। लेकिन एक बार वहाँ, वास्तविक प्रविष्टि हे (1) है। इसका सबसे बड़ा लाभ यह std::listहै कि आप उन्हें एक साथ जल्दी से विभाजित कर सकते हैं ... यदि आप मानों की एक पूरी श्रृंखला को किसी भिन्न पर ले जाते हैं std::list, तो पूरा ऑपरेशन O (1) है। सूची में संदर्भों को अमान्य करना भी बहुत कठिन है, जो कभी-कभी महत्वपूर्ण हो सकता है।

एक सामान्य नियम के रूप में, मैं पसंद std::dequeकरता हूं std::vector, जब तक कि मुझे एक लाइब्रेरी के लिए डेटा को पारित करने में सक्षम होने की आवश्यकता नहीं है जो कच्चे सरणी की अपेक्षा करता है। std::vectorसन्निहित गारंटी है, इसलिए &v[0]इस उद्देश्य के लिए काम करता है। मुझे याद नहीं है कि पिछली बार मैंने एक का उपयोग किया था std::list, लेकिन यह लगभग निश्चित रूप से था क्योंकि मुझे शेष वैध संदर्भों के बारे में मजबूत छाप की जरूरत थी।


FWIW, std :: deque में संदर्भों के बारे में बहुत अच्छी गारंटी है। Iterators आसानी से अमान्य हैं, लेकिन सदस्यों को संकेत dequeue पर संचालन के लिए बहुत मजबूत हैं।
बेन

बहुत बढ़िया जवाब। लेकिन मेरे पास एक अतिरिक्त प्रश्न है: जो तेजी से पुनरावृति करना है? मेरे पास वस्तुओं का एक सेट है, वे वास्तव में अक्सर सम्मिलित या हटाए नहीं जाते हैं, लेकिन मुझे जितनी जल्दी हो सके वस्तुओं पर पुनरावृति करने की आवश्यकता है। कौन सा तेज है?
birgersp

अच्छी जानकारी। मैंने निम्नलिखित कथन को सबसे उपयोगी पाया ... "क्यूटी पुस्तकालय क्यूएलिस्ट वस्तुओं के उपयोग के लिए बहुत अधिक उपकार करता है"। मेरे उपयोग के मामले में, मैं एक qableablewidget के साथ काम कर रहा हूं, जिसे QList और QListString पसंद है। इसलिए, अपने उपयोग के मामले को QVector और QList के बीच अपना निर्णय निर्धारित करें।
15 '20

1
क्या आपने इसके std::dequeखिलाफ एक बेंचमार्क किया है std::vector? आप हैरान रह जाएंगे ...
मार्क मुतज़ - mmutz

4
कृपया ध्यान रखें कि प्रलेखन को Qt डेवलपर्स से शिकायत के बाद अद्यतन किया गया है कि QList एक डिफ़ॉल्ट कंटेनर के रूप में एक खराब सिफारिश है। अब यह बताता है: " QVector आपकी डिफ़ॉल्ट पहली पसंद होनी चाहिए। [...] हालाँकि, QList का उपयोग मापदंडों को वापस करने और मूल्यों को वापस करने के लिए Qt API में किया जाता है। QList का उपयोग उन API के साथ इंटरफ़ेस के लिए करें। " (QList प्रलेखन
AntonyG

64

चीजें बदल गई

अब हम Qt 5.8 में हैं और चीजें बदल गई हैं, इसलिए प्रलेखन। यह इस सवाल का एक स्पष्ट और अलग जवाब देता है:

QVectorआपकी पहली पसंद होना चाहिए। QVector<T>आमतौर पर QList<T> की तुलना में बेहतर प्रदर्शन देगा , क्योंकि QVector<T>हमेशा अपने आइटम को क्रमिक रूप से मेमोरी में संग्रहीत करता है, जहां QList<T>अपने आइटम को ढेर पर आवंटित करेगा जब तक कि sizeof(T) <= sizeof(void*)और टी को Q_MOVABLE_TYPEया तो एक या एक Q_PRIMITIVE_TYPEप्रयोग के रूप में घोषित नहीं किया गया हो Q_DECLARE_TYPEINFO

QListएक स्पष्टीकरण के लिए उपयोग करने के पेशेवरों और विपक्ष देखें । हालांकि, QListमापदंडों और रिटर्निंग मानों के लिए Qt API में उपयोग किया जाता है। QListउन एपीआई के साथ इंटरफेस का उपयोग करें ।


2
यह ऊपर जाना चाहिए, और अब उत्तर के रूप में स्वीकार किया जाना चाहिए।
यमोरो

12

के QVectorसमान है std::vectorQLinkedListके समान है std::listQListएक सूचकांक आधारित वेक्टर है, लेकिन मेमोरी की स्थिति की गारंटी नहीं है (जैसे std::deque)।


3

QtList डॉक्टर से:

  • अधिकांश मामलों में इस्तेमाल किया जाने वाला QList। एक हजार वस्तुओं के साथ संरचनाओं के लिए, मध्य में कुशल सम्मिलन को सक्षम करता है, और अनुक्रमित-पहुंच प्रदान करता है। prepend()और append()बहुत तेजी से स्मृति आंतरिक सरणी के दोनों सिरों पर उपदेशित है। QList<T>T प्रकार के पॉइंटर का एक सरणी है। यदि T में एक पॉइंटर या Qt साझा-जैसे पॉइंटर प्रकार है, तो ऑब्जेक्ट सीधे सरणी में संग्रहीत होता है।

  • QVectorका एक बहुत के मामले में प्राथमिकता दी जानी करने के लिए append()या insert()आकार के बाद से एक सूचक की तुलना में बड़ा के साथ नए आइटम का QVectorएक भी ढेर आवंटन में अपनी वस्तुओं के लिए आवंटित स्मृति। QListनए आइटम के परिशिष्ट में डालने के लिए , ढेर पर नए आइटम के मेमोरी आवंटन की आवश्यकता होती है। संक्षेप में, यदि आप चाहते हैं कि आइटम आसन्न मेमोरी पोज़िशन्स पर कब्जा कर लें, या यदि आपके आइटम एक पॉइंटर से बड़े हैं और आप प्रविष्टि समय पर व्यक्तिगत रूप से ढेर पर उन्हें आवंटित करने के ओवरहेड से बचना चाहते हैं, तो उपयोग करें QVector


-2

QVector एक सरणी की तरह है जो आकार (वृद्धि या कमी) को बदल सकता है लेकिन यह भारी लेनदेन और गणना और समय के साथ आता है।

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

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

यदि आपके पास उन मदों की सूची है, जो आपको आकार बदलने की उम्मीद नहीं करते हैं, QVectorतो शायद अच्छा है, लेकिन आमतौर पर QLinkedListइसका उपयोग अधिकांश उद्देश्यों के लिए किया जाता है।


3
-1: QVector भारी लेनदेन के साथ नहीं आता है जैसा कि आप दावा करते हैं क्योंकि यह प्रचार करता है और इसमें अपील और पॉपिंग के लिए एक अच्छी वृद्धि / सिकुड़न रणनीति है। Prepend / सम्मिलन के लिए वास्तव में बढ़ते डेटा पर्वतमाला की आवश्यकता होती है, लेकिन जब से वे स्मृति में निरंतर होते हैं, तो यह बहुत जल्दी किया जाता है (कैश निरंतर डेटा के साथ अच्छी तरह से काम कर सकता है, बिखरे हुए ढेर के साथ QList के रूप में)। आपका दूसरा कथन जो QLinkedList का उपयोग अधिकांश उद्देश्यों के लिए किया जाता है, वह गलत है। इसका सबसे अधिक उपयोग किया जाता है। आप इसे QList के साथ भ्रमित कर रहे हैं?
डेरमनू
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.