एसटीडी :: वेक्टर तत्व सन्निहित होने की गारंटी है?


111

मेरा सवाल सरल है: एसटीडी :: वेक्टर तत्व सन्निहित होने की गारंटी है? आदेश शब्द में, क्या मैं सूचक का उपयोग std के पहले तत्व के लिए कर सकता हूँ :: C- सरणी के रूप में वेक्टर?

यदि मेरी मेमोरी मुझे अच्छी तरह से परोसती है, तो C ++ मानक ने ऐसी कोई गारंटी नहीं दी। हालांकि, एसटीडी :: वेक्टर आवश्यकताएं ऐसी थीं कि अगर तत्व सन्निहित नहीं थे, तो उनसे मिलना लगभग असंभव था।

क्या कोई इसे स्पष्ट कर सकता है?

उदाहरण:

std::vector<int> values;
// ... fill up values

if( !values.empty() )
{
    int *array = &values[0];
    for( int i = 0; i < values.size(); ++i )
    {
        int v = array[i];
        // do something with 'v'
    }
}

मुझे पता है कि अगर आप valuesउस ifब्लॉक के अंदर म्यूट करते हैं तो आप मुश्किल में हैं । हालांकि, मुझे आपके सवाल का जवाब नहीं पता है, इसलिए मैं सिर्फ एक टिप्पणी छोड़ रहा हूं। :)
ग्रेग डी

@Greg: क्या परेशानी - आप थोड़ा विस्तृत कर सकते हैं?
रीयूनैन

मुझे लगता है कि उनका मतलब था कि नए मूल्यों को धक्का एक "realloc" को ट्रिगर कर सकता है जिससे सरणी अमान्य हो जाएगी।
मार्टिन कॉट

उस म्यूट को कॉल valuesकरता है, विशेष रूप से जो इसका आकार बदलता है (उदाहरण के लिए push_back()), अंतर्निहित वेक्टर के एक पुनर्स्थापन का संकेत दे सकता है जो कि कॉपी किए गए पॉइंटर को अमान्य करता है array। यह वेक्टर में सूचक के बजाय वेक्टर का उपयोग करने के पीछे समान सिद्धांत है। :)
ग्रेग डी

1
हाँ, मैंने मानों को स्पष्ट करने का प्रयास करने के लिए चारों ओर `` लगा दिया है मैं कक्षा के बारे में बात कर रहा था, न कि इसके भीतर निहित मान। :) दुर्भाग्यपूर्ण नामकरण और वह सब। मुझे नहीं लगता कि यह वास्तव में सामान्य मामले में एक मुद्दा है, जहां यह सवाल हालांकि प्रासंगिक है - कोई व्यक्ति मेमोरी को एक पॉइंटर क्यों पकड़ लेगा, फिर पॉइंटर का उपयोग करने के बजाय वेक्टर के साथ मिलाना शुरू करें? मूर्खता।
ग्रेग डी

जवाबों:


118

यह C ++ 98 मानक से उचित रूप से छूट गया था लेकिन बाद में TR के हिस्से के रूप में जोड़ा गया। आगामी C ++ 0x मानक निश्चित रूप से इसे आवश्यकता के रूप में समाहित करेगा।

N2798 से (C ++ 0x का ड्राफ्ट):

23.2.6 वर्ग टेम्पलेट वेक्टर [वेक्टर]

1 एक वेक्टर एक अनुक्रम कंटेनर है जो यादृच्छिक अभिगम पुनरावृत्तियों का समर्थन करता है। इसके अलावा, यह अंत में लगातार समय डालने और मिटाए जाने का समर्थन (परिशोधन) करता है; बीच में डालें और मिटाएं रैखिक समय लें। भंडारण प्रबंधन को स्वचालित रूप से नियंत्रित किया जाता है, हालांकि दक्षता में सुधार के लिए संकेत दिए जा सकते हैं। एक वेक्टर के तत्वों को संचित रूप से संग्रहीत किया जाता है, जिसका अर्थ है कि यदि v एक वेक्टर है जहां T, बूल के अलावा कुछ प्रकार है, तो यह पहचान का पालन करता है & v [n] == & v [0] + n सभी के लिए <<n> v .Size ()।


3
यह आईएसओ 14882, 2 वें संस्करण में भी कहा गया है: धारा 23.2.4 [lib.vector]: "वेक्टर के तत्व संचित रूप से संग्रहीत होते हैं, जिसका अर्थ है कि यदि v एक वेक्टर है <T, एलोकेटर> जहां T कुछ प्रकार से कहा गया है बूल, तो यह पहचान का पालन करता है & v [n] == & v [0] + n सभी के लिए 0 <= n <v.size ()। "
माइक कैरन

4
इसलिए s, TR, TC, :) वास्तव में C ++ 03 को C ++ 98-TC1 (तकनीकी गलियारा) भी कहा जाता है, जो मैंने पढ़ा है
जोहान्स स्काउब -

2
वैक्टर के वैक्टर के बारे में क्या? अंतिम समूह के आंतरिक वैक्टर के बाद innernner वैक्टर सही हैं?
हुसैन तुगरुल बायुकिसिक

1
@huseyin tugrul buyukisik क्या आपने इसका उत्तर सीखा? मैं यह भी सोच रहा हूं कि यह कैसे काम करता है
डेविड डोरिया

1
@huseyin tugrul buyukisik यह सच है, लेकिन यह बाद के उदाहरण std::vectorहैं जो सन्निहित हैं। जैसे: std::vector<std::vector<int>> vतत्वों v[0]में v[1], ..., स्मृति में बाद में संग्रहीत होते हैं, लेकिन तत्व v[0].back()और v[1].front()होने की गारंटी नहीं है।
जारज़ेक

27

जैसा कि अन्य जवाबों में कहा गया है, वेक्टर की सामग्री निरंतर होने की गारंटी है (बूल की अजीबता को छोड़कर)।

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


1
तत्वों को अभी भी एक सन्निहित मेमोरी ब्लॉक में संग्रहीत किया जाएगा, यह सिर्फ एक अलग स्थान पर होगा। सवाल विशेष रूप से संदर्भ के बारे में था।
दिमा

2
लेकिन मौजूदा संकेत और पुनरावृत्तियों को अमान्य कर दिया जाएगा।
बिल लिंच

अच्छी बात। आपको अपने जवाब में यह स्पष्ट करना चाहिए कि आपका क्या मतलब है।
दीमा

मेरे लिए सबसे उपयोगी उत्तर
कॉफ़ीडवेल्टर

अब मुझे पता है कि मेरा कार्यक्रम कल क्यों सेगफॉल्ट कर रहा था, जब मैंने कुछ तत्वों को हटाने वाले दोहरे लूप में इसके माध्यम से लूप किया था :) धन्यवाद!
15:28 बजे user2891462

9

मानक वास्तव में गारंटी देता है कि vectorस्मृति में एक निरंतर है और यह उस फ़ंक्शन &a[0]को पारित किया जा सकता है Cजो किसी सरणी की अपेक्षा करता है।

इस नियम का अपवाद यह है vector<bool>कि केवल प्रति बिट एक का उपयोग करता है, boolहालांकि इसमें निरंतर मेमोरी होती है इसका उपयोग एक के रूप में नहीं किया जा सकता है bool*(इसे व्यापक रूप से एक गलत अनुकूलन और एक गलती माना जाता है)।

BTW, आप पुनरावृत्तियों का उपयोग क्यों नहीं करते हैं? यही वे लिए हैं।


1
> BTW, आप पुनरावृत्तियों का उपयोग क्यों नहीं करते? यही वे लिए हैं। हो सकता है कि उन्होंने इस विषय पर अलेक्ज़ानरेस्कु के नए पेपर को पढ़ा: बूस्टोन.com
Nemanja Trifunovic

इस लिंक के लिए धन्यवाद, मैं इसे अपनी पठन सूची में
डालूंगा

मावहा, हर कोई इन दिनों उस प्रस्तुति के बारे में बात कर रहा है। देखिए, इस बारे में चर्चा अभी भी गर्म है: group.google.com/group/comp.lang.c++.moderated/browse_thread/…
जोहान्स स्काउब -

यदि आप इसे ध्यान से पढ़ते हैं, तो अलेक्जेंड्रेस्कु का लेख वास्तव में यह नहीं कहता है कि "सी ++ में पुनरावृत्तियों का उपयोग न करें", यह कहता है "चेक आउट डी"। उस कागज़ का वह दृष्टिकोण जो किसी भी मौजूदा भाषा और रूपरेखा के समान है, जो कार्यात्मक विरासत (सूची, योजना, हास्केल) को अवशोषित कर लेता है और मुझे गंभीरता से संदेह है कि क्या अभी तक एक और-सी-आधारित-वाक्यविन्यास बेहतर के लिए एक आदर्श प्रारंभिक बिंदु है सूची हैंडलिंग। पिछले साल कुछ समय मैंने संक्षेप में सी # के बजाय पहले से ही स्थापित भाषा को बेहतर बनाने की दिशा में अपनी प्रतिभा को बदलने के लिए उसे मनाने की कोशिश की, लेकिन मुझे कोई सफलता नहीं मिली! :)
डैनियल ईयरविकेर

6

जैसा कि अन्य ने पहले ही कहा है, vectorआंतरिक रूप से वस्तुओं के एक आकस्मिक सरणी का उपयोग करता है। जब भी किसी गैर-कॉन्स्टेबल सदस्य फ़ंक्शन को IIRC कहा जाता है, तो उस सरणी में पॉइंटर्स को अमान्य माना जाना चाहिए।

हालाँकि, एक अपवाद है !!

vector<bool>अंतरिक्ष को बचाने के लिए डिज़ाइन किया गया एक विशेष कार्यान्वयन है, ताकि प्रत्येक बूल केवल एक बिट का उपयोग करे। अंतर्निहित सरणी बूल की एक सन्निहित सरणी नहीं है और सरणी अंकगणित इस vector<bool>तरह काम नहीं vector<T>करेगा।

(मुझे लगता है कि यह भी संभव है कि यह वेक्टर के किसी भी विशेषज्ञता का सच हो सकता है, क्योंकि हम हमेशा एक नया लागू कर सकते हैं। हालांकि, std::vector<bool>एकमात्र, गलत, मानक विशेषज्ञता है, जिस पर सरल सूचक अंकगणित काम नहीं करेगा।)


उपयोगकर्ता को विशेषज्ञ की अनुमति नहीं है std::vector, और अन्य सभी वैक्टरों को सन्निहित भंडारण का उपयोग करना आवश्यक है। इसलिए, std::vector<bool>(सौभाग्य से) एकमात्र मानक वेक्टर है जो अजीब है। (मैं इस राय के बारे में दृढ़ता से कहता हूं कि इस विशेषज्ञता को पदावनत किया जाना चाहिए और उदाहरण के लिए इसे एक std::dynamic_bitsetही कार्यक्षमता के साथ प्रतिस्थापित किया जाना चाहिए । यह एक खराब डेटा संरचना नहीं है, यह सिर्फ एक वेक्टर नहीं है।)
आर्ने वोगेल

3

मुझे यह धागा मिला क्योंकि मेरे पास एक उपयोग का मामला है जहां सन्निहित स्मृति का उपयोग करने वाले वैक्टर एक फायदा है।

मैं सीख रहा हूं कि ओपनजीएल में वर्टेक्स बफर ऑब्जेक्ट्स का उपयोग कैसे करें। मैंने बफर तर्क सम्‍मिलित करने के लिए एक रैपर क्‍लास बनाया है, इसलिए मुझे बस बोट बनाने के लिए फ्लोट्स की एक सरणी और कुछ कॉन्‍फ़िगर मानों को पास करना होगा। मैं उपयोगकर्ता इनपुट के आधार पर एक फ़ंक्शन से एक बफर उत्पन्न करने में सक्षम होना चाहता हूं, इसलिए संकलन समय पर लंबाई ज्ञात नहीं है। इस तरह से कुछ करना सबसे आसान उपाय होगा:

void generate(std::vector<float> v)
{
  float f = generate_next_float();
  v.push_back(f);
}

अब मैं वेक्टर की झांकियों को ओपनजीएल के बफर-संबंधित कार्यों के लिए एक सरणी के रूप में पारित कर सकता हूं। यह सरणी की लंबाई निर्धारित करने के लिए आकार की आवश्यकता को भी हटा देता है।

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


2
इस फ़ंक्शन का मेरे लिए कोई मतलब नहीं है। क्या आप एक संदर्भ या एक सूचक होने के vबजाय vखुद को पारित करने का मतलब है? क्योंकि vअकेले गुजरने से फ़ंक्शन के अंदर कॉपी बनने का कारण होगा, जो फ़ंक्शन के समाप्त होने के बाद अस्तित्व में नहीं रहेगा। इस प्रकार आप वेक्टर को केवल कार्य समाप्त होने पर वेक्टर को हटाने के लिए कुछ धक्का दे रहे हैं।
जॉन्बेकर

1

cplusplus.com:

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


1

हां, एक एसटीडी के तत्व :: वेक्टर को सन्निहित होने की गारंटी है।


सही। मुझे लगता है कि मैं उन लोगों का बहुत अधिक उपयोग करता हूं :)
Ben
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.